Spring 4 - Custom SecurityExpression with Service

僤鯓⒐⒋嵵緔 提交于 2019-12-08 05:58:08

问题


In one of my controllers, I have the need to secure a method with more granular means than a role.

I've got a MethodSecurityExpressionHandler created, but I can't figure out how to access one of my @Services in it.

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = false)
    public class CustomMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Autowired
    ApplicationContext applicationContext;
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        CustomMethodSecurityExpressionHandler handler = new  CustomMethodSecurityExpressionHandler();
        handler.setApplicationContext(applicationContext);
        return super.createExpressionHandler();
    }
    @Bean
    public MethodSecurityExpressionHandler expressionHandler() {
        return new CustomMethodSecurityExpressionHandler();
    }
}

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
                                                                              MethodInvocation invocation) {
        final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(this.trustResolver);
        root.setRoleHierarchy(getRoleHierarchy());

        return root;
    }
}


public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    private Object filterObject;
    private Object returnObject;
    private Object target;

    //**This is what I need to work**
    @Autowired
    private RepositoryService repositoryService;

    public boolean canViewFolder(String uuid){
        User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
         return repositoryService.checkFolderPermissions(currentUser.getUsername(), uuid);
    }

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

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

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

    public Object getThis() {
        return target;
    }

}

回答1:


Create a setter for your RepositoryService in CustomMethodSecurityExpressionRoot

Override setApplicationContext in CustomMethodSecurityExpressionHandler to have the applicationContext you pass in at an accessible level.

In createSecurityExpressionRoot using the applicationContext pass in the RepositoryService bean from your context. Code is below. Also note the changes I made to createExpressionHandler() and expressionHandler(). In create ExpressionHandler you are calling the super which just uses a default implementation, not the object you just newed two lines earlier. In expressionHandler() you are creating a new instance of CustomMethodSecurityExpressionHandler() not retrieving the one you are creating in createExpressionHandler().

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = false)
    public class CustomMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Autowired
    ApplicationContext applicationContext;
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        CustomMethodSecurityExpressionHandler handler = new  CustomMethodSecurityExpressionHandler();
        handler.setApplicationContext(applicationContext);
        return handler;
    }
    @Bean
    public MethodSecurityExpressionHandler expressionHandler() {
        return createExpressionHandler();
    }
}

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
    private ApplicationContext applicationContext;
    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
                                                                              MethodInvocation invocation) {
        final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(this.trustResolver);
        root.setRoleHierarchy(getRoleHierarchy());
        root.setRepositoryService(applicationContext.getBean(RepositoryService.class);
        return root;
    }

    @Override
    protected void setApplicationContext(applicationContext){
        super.setApplicationContext(applicationContext);
        this.applicationContext = applicationContext;
    }
}


public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    private Object filterObject;
    private Object returnObject;
    private Object target;
    private RepositoryService repositoryService;

    public boolean canViewFolder(String uuid){
        User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
         return repositoryService.checkFolderPermissions(currentUser.getUsername(), uuid);
    }

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

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

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

    public Object getThis() {
        return target;
    }

    public void setRepositoryService(RepositoryService repositoryService){
        this.repositoryService = repositoryService;
    }
}


来源:https://stackoverflow.com/questions/39090783/spring-4-custom-securityexpression-with-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!