Spring security 使用面向方面的编程 (AOP) 将安全代码编织/交织到您自己的代码库中。这在 Spring 中的工作方式是使用定义注入点的注释 (cfr.pointcuts) 以允许在您自己的代码之前/之后/内部执行额外的逻辑 (cfr.advice)。
Interceptors 扫描您的代码库以查找join points(即,对于 Spring,当使用特定注释标记时,这始终是方法执行),并将根据您使用的拦截点(即接口)执行额外的特定逻辑。
要启用此行为,可以添加配置:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class ConfigGlobalMethodSecurity extends GlobalMethodSecurityConfiguration {
...
}
特别是对于PreAuthorize,PrePostAdviceReactiveMethodInterceptor 负责查找带有PreAutorize 注释的方法。反过来,这将委托给PreInvocationAuthorizationAdvice,在此处将ReactiveMethodSecurityConfiguration 配置为ExpressionBasedPreInvocationAdvice。
这在内部使用默认表达式处理程序DefaultMethodSecurityExpressionHandler 创建SecurityExpressionRoot。这个SecurityExpressionRoot 的实际实现将定义如何处理PreAuthorize 中的表达式以及需要执行什么逻辑。
SecurityExpressionRoot 定义了您的PreAuthorize 中允许使用的表达式,例如hasRole。
要添加其他表达式或扩展默认权限逻辑,您需要提供SecurityExpressionRoot 的自定义实现以及可选的自定义PermissionEvaluator。例如。如果你想写@PreAuthorize("hasKnowledgeOf('AOP')")。
public class CustomMethodSecurityExpressionRoot
extends SecurityExpressionRoot
implements MethodSecurityExpressionOperations {
private final PermissionEvaluator permissionEvaluator;
private final Authentication authentication;
private Object filterObject;
private Object returnObject;
private Object target;
public CustomMethodSecurityExpressionRoot(
Authentication authentication,
PermissionEvaluator permissionEvaluator) {
super(authentication);
this.authentication = authentication;
this.permissionEvaluator = permissionEvaluator;
super.setPermissionEvaluator(permissionEvaluator);
}
// new expression to check if the requested knowledge is present
public boolean hasKnowledgeOf(String context) {
// provide logic that performs the check
}
@Override
public void setFilterObject(Object filterObject) {
this.filterObject = filterObject;
}
@Override
public Object getFilterObject() {
return filterObject;
}
@Override
public void setReturnObject(Object returnObject) {
this.returnObject = returnObject;
}
@Override
public Object getReturnObject() {
return returnObject;
}
@Override
public Object getThis() {
return target;
}
}
和
@Configuration
public class CustomPermissionEvaluator
implements PermissionEvaluator {
@Override
public boolean hasPermission(
Authentication authentication,
Object targetDomainObject,
Object permission) {
// define your custom permission logic here
}
@Override
public boolean hasPermission(
Authentication authentication,
Serializable targetId,
String targetType,
Object permission) {
// define your custom permission logic here
}
}
完成配置并将求值器传递给表达式根。
public class CustomMethodSecurityExpressionHandler
extends DefaultMethodSecurityExpressionHandler {
PermissionEvaluator permissionEvaluator;
public CustomMethodSecurityExpressionHandler(PermissionEvaluator permissionEvaluator) {
this.permissionEvaluator = permissionEvaluator;
super.setPermissionEvaluator(permissionEvaluator);
}
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication,
MethodInvocation invocation) {
CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(
authentication,
permissionEvaluator);
root.setTrustResolver(new AuthenticationTrustResolverImpl());
root.setRoleHierarchy(getRoleHierarchy());
return root;
}
}
和
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class ConfigGlobalMethodSecurity extends GlobalMethodSecurityConfiguration {
@Autowired CustomPermissionEvaluator permissionEvaluator;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new CustomMethodSecurityExpressionHandler(permissionEvaluator);
}
}