Spring security use PrePostAnnotationSecurityMetadataSource
to find the @PreAuthorize
and convert the Spring-EL expression to ConfigAttribute
.
You can implement your MyAuthorizationCheckAnnotationSecurityMetadataSource
and override getAttributes
method to convert your enums to ConfigAttribute
too;
write your code like this:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAuthorizationCheck {
Application app();
AccessLevel level();
}
public class MyAuthorizationCheckAnnotationSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
private final PrePostInvocationAttributeFactory attributeFactory;
public MyAuthorizationCheckAnnotationSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory) {
this.attributeFactory = attributeFactory;
}
@Override
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return Collections.emptyList();
}
this.logger.trace(LogMessage.format("Looking for FddApi annotations for method '%s' on target class '%s'",
method.getName(), targetClass));
MyAuthorizationCheck myAuthorization = findAnnotation(method, targetClass, MyAuthorizationCheck.class);
if (myAuthorization == null) {
this.logger.trace("No expression annotations found");
return Collections.emptyList();
}
Application app = myAuthorization.app();
AccessLevel level = myAuthorization.level();
// build the Spring-EL expression from enums
String expr = "hasPermission('" + app.name() + "_" + level.name() + "')";
PreInvocationAttribute pre = this.attributeFactory.createPreInvocationAttribute(null, null, expr);
return CollUtil.newArrayList(pre);
}
// other method can copy from PrePostAnnotationSecurityMetadataSource
...
}
then registe the MyAuthorizationCheckAnnotationSecurityMetadataSource.
our code need PreInvocationAuthorizationAdviceVoter to check permission, so need enable the prePostEnabled
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(
getExpressionHandler());
return new MyAuthorizationCheckAnnotationSecurityMetadataSource(attributeFactory);
}
}
Finally you can use the @MyAuthorizationCheck like this:
@MyAuthorizationCheck(app = Application.USER_MANAGEMENT, level = AccessLevel.EDIT)
public String editUSer(User user);