Tôi đã đăng a detailed article khi triển khai Run-As kết hợp với @PreAuthorize
.
1) Thực hiện RunAsManager
của riêng bạn để tạo Authentication
để sử dụng trong khi thực hiện phương pháp dựa trên bất kỳ logic tùy chỉnh nào. Ví dụ dưới đây sử dụng một chú thích tùy chỉnh cung cấp các vai trò bổ sung:
public class AnnotationDrivenRunAsManager extends RunAsManagerImpl {
@Override
public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
if(!(object instanceof ReflectiveMethodInvocation) || ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class) == null) {
return super.buildRunAs(authentication, object, attributes);
}
String roleName = ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class).value();
if (roleName == null || roleName.isEmpty()) {
return null;
}
GrantedAuthority runAsAuthority = new SimpleGrantedAuthority(roleName);
List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();
// Add existing authorities
newAuthorities.addAll(authentication.getAuthorities());
// Add the new run-as authority
newAuthorities.add(runAsAuthority);
return new RunAsUserToken(getKey(), authentication.getPrincipal(), authentication.getCredentials(),
newAuthorities, authentication.getClass());
}
}
thi này sẽ tìm kiếm một chú thích tùy chỉnh @RunAsRole
trên một phương pháp bảo vệ (ví dụ @RunAsRole("ROLE_AUDITOR")
) và, nếu tìm thấy, sẽ bổ sung thêm thẩm quyền nhất định (ROLE_AUDITOR
trong trường hợp này) vào danh sách các cơ quan có thẩm quyền. RunAsRole
chính nó chỉ là một chú thích tùy chỉnh đơn giản.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RunAsRole {
String value();
}
2) Khởi tạo người quản lý:
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<property name="key" value="my_run_as_key"/>
</bean>
3) đăng ký nó:
<global-method-security pre-post-annotations="enabled" run-as-manager-ref="runAsManager">
<expression-handler ref="expressionHandler"/>
</global-method-security>
4) sử dụng Ví dụ trong một Bộ điều khiển:
@Controller
public class TransactionLogController {
@PreAuthorize("hasRole('ROLE_REGISTERED_USER')") //Authority needed to access the method
@RunAsRole("ROLE_AUDITOR") //Authority added by RunAsManager
@RequestMapping(value = "/transactions", method = RequestMethod.GET) //Spring MVC configuration. Not related to security
@ResponseBody //Spring MVC configuration. Not related to security
public List<Transaction> getTransactionLog(...) {
... //Invoke something in the backend requiring ROLE_AUDITOR
{
... //User does not have ROLE_AUDITOR here
}
EDIT: Giá trị của key
trong RunAsManagerImpl
có thể là bất kỳ thứ gì bạn muốn. Dưới đây là đoạn trích từ Spring docs về việc sử dụng nó:
Để đảm bảo mã độc không tạo ra một RunAsUserToken
và hiện nó bảo đảm chấp nhận bởi các RunAsImplAuthenticationProvider
, các hash của một phím được lưu trữ trong tất cả các thẻ được tạo ra. Các RunAsManagerImpl
và RunAsImplAuthenticationProvider
được tạo ra trong bối cảnh đậu với cùng then chốt:
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<bean id="runAsAuthenticationProvider"
class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
Bằng việc sử dụng cùng quan trọng, mỗi RunAsUserToken
thể được xác nhận nó đã được tạo ra bởi một số được phê duyệt RunAsManagerImpl
.RunAsUserToken
không thay đổi sau khi tạo vì lý do bảo mật.
Chính xác "my_run_as_key" được sử dụng để làm gì? - Tôi không thể hiểu được điều này. Tôi có thể đọc cùng một hướng dẫn bạn trích dẫn ở đây, nhưng chìa khóa này chỉ không có ý nghĩa với tôi. –
@DanielBo Giá trị có thể là bất cứ điều gì bạn muốn. Về cơ bản nó là một mật khẩu. Tôi đã cập nhật câu trả lời để trích dẫn Tài liệu mùa xuân về lý do tại sao cần. – kaqqao