获取授权前/授权后的方法名称

Sri*_*air 5 spring spring-security

我正在为 Spring 安全性编写自己的 PermissionEvaluator,我想做的事情之一就是找出它所保护的方法的名称。

例如,如果没有图片中的方法名称,我有类似的内容:

postAuthorize("hasPermission(returnObject,'read')")
Event getEvent(int evendId) {
...
}
Run Code Online (Sandbox Code Playgroud)

public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
    if(targetDomainObject instanceof Event) {

        return hasPermission(authentication, targetDomainObject, permission);
    }
    return targetDomainObject == null;
}
Run Code Online (Sandbox Code Playgroud)

但我还需要方法名称“getEvent”可供 hasPermission 使用。我可以通过在 hasPermission 调用中手动传递它来完成此操作,如下所示:

@PostAuthorize("hasPermission(new com.example.AuthZObject(returnObject,'getEvent'),'read')")
Event getEvent(int eventId);
Run Code Online (Sandbox Code Playgroud)

但有没有更自动化的方法来做到这一点?

Rob*_*nch 4

@Ralph 这里的想法非常正确。第一步是创建 MethodSecurityExpressionOperations 的自定义实现,该实现可以在其上存储 Method 并使用它来计算表达式。例如:

public class MyMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
    private Object filterObject;
    private Object returnObject;
    private Object target;
    private Method method;

    public MyMethodSecurityExpressionRoot(Authentication a) {
        super(a);
    }

    // allow the method to be set    
    public void setMethod(Method m) {
        this.method = m;
    }

    // optionally expose the method to be accessed in expressions    
    public Method getMethod() {
        return method;
    }

    // create a method that will perform the check with 
    // the method name transparently for you    
    public boolean hasMethodPermission(Object target, Object permission) {
        boolean result = false;

        // do your calculations using the method member variable 
        // i.e. method.getName() and the arguments passed in
        // of course you could delegate to another object if you want
        // i.e.
        // return hasPermission(new com.example.AuthZObject(target,method.getName()),permission));
        // or you could do the logic right here

        return result;
    }

    // implement the interface and provide setters

    public void setFilterObject(Object filterObject) {
        this.filterObject = filterObject;
    }

    public Object getFilterObject() {
        return filterObject;
    }

    public void setReturnObject(Object returnObject) {
        this.returnObject = returnObject;
    }

    public Object getReturnObject() {
        return returnObject;
    }

    public void setThis(Object target) {
        this.target = target;
    }

    public Object getThis() {
        return target;
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来扩展 DefaultMethodSecurityExpressionHandler 并使用自定义表达式根。

public class MySecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler{

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation){
        MyMethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(new AuthenticationTrustResolverImpl());
        root.setRoleHierarchy(getRoleHierarchy());
        root.setMethod(invocation.getMethod());
        return root;
    }
}
Run Code Online (Sandbox Code Playgroud)

配置 MySecurityExpressionHandler 后,您应该能够使用以下内容:

@PostAuthorize("hasMethodPermission(returnObject,'read')")
Event getEvent(int eventId);
Run Code Online (Sandbox Code Playgroud)