3

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

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

此注释的处理程序应该能够决定用户是否具有权限。

任何指针如何实现这一目标?

谢谢你。

4

2 回答 2

1

Spring 安全性用于PrePostAnnotationSecurityMetadataSource查找@PreAuthorizeSpring-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);
于 2022-01-10T02:34:13.030 回答
0

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

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

@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')")
于 2013-08-07T09:05:56.920 回答