【问题标题】:Custom annotation with spring security带有弹簧安全性的自定义注释
【发布时间】:2013-08-08 11:04:43
【问题描述】:

我已阅读 Spring Security 文档并了解到我可以使用以下注释来检查主题是否有权编辑用户。

@PreAuthorize("hasPermission('USER_EDIT')")
public String editUSer(User user);

我想做的是编写我的自定义注释 MyAutorizationCheck 并像下面这样使用它

@MyAuthorizationCheck(Application.USER_MANAGEMENT, AccessLevel.EDIT)
public String editUSer(User user);

Application 和 AccessLevel 是枚举。

enum Application{
    USER_MANAGEMENT, ORDER_MANAGEMENT
}

enum AccessLevel{
    READ, CREATE, UPDATE, DELETE
}

这个注解的处理程序应该能够决定用户是否有权限。

任何指针如何实现这一点?

谢谢。

【问题讨论】:

    标签: spring-security


    【解决方案1】:

    Spring 安全使用PrePostAnnotationSecurityMetadataSource 查找@PreAuthorize 并将Spring-EL 表达式转换为ConfigAttribute

    您也可以实现 MyAuthorizationCheckAnnotationSecurityMetadataSource 并覆盖 getAttributes 方法以将您的枚举转换为 ConfigAttribute

    这样写你的代码:

    @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
        ...
    
    }
    

    然后注册 MyAuthorizationCheckAnnotationSecurityMetadataSource。

    我们的代码需要 PreInvocationAuthorizationAdviceVoter 来检查权限,所以需要启用 prePostEnabled

    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class CustomSecurityConfig extends GlobalMethodSecurityConfiguration {
    
        @Override
        protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
            ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(
                    getExpressionHandler());
            return new MyAuthorizationCheckAnnotationSecurityMetadataSource(attributeFactory);
        }
    }
    

    最后你可以像这样使用@MyAuthorizationCheck:

    @MyAuthorizationCheck(app = Application.USER_MANAGEMENT, level = AccessLevel.EDIT)
    public String editUSer(User user);
    

    【讨论】:

      【解决方案2】:

      这不是对您的问题的直接回应。

      作为一种解决方法,您可以继续使用内置注释:

      @PreAuthorize("hasPermission('USER_MANAGEMENT_READ')")
      @PreAuthorize("hasPermission('USER_MANAGEMENT_CREATE')")
      @PreAuthorize("hasPermission('USER_MANAGEMENT_UPDATE')")
      @PreAuthorize("hasPermission('USER_MANAGEMENT_DELETE')")
      
      @PreAuthorize("hasPermission('ORDER_MANAGEMENT_READ')")
      @PreAuthorize("hasPermission('ORDER_MANAGEMENT_CREATE')")
      @PreAuthorize("hasPermission('ORDER_MANAGEMENT_UPDATE')")
      @PreAuthorize("hasPermission('ORDER_MANAGEMENT_DELETE')")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-15
        • 1970-01-01
        • 2022-06-20
        • 2012-08-04
        • 2011-06-30
        • 2015-12-20
        • 2011-07-03
        • 1970-01-01
        相关资源
        最近更新 更多