Spring 4 — Custom SecurityExpression с сервисом

В одном из моих контроллеров мне нужно защитить метод более детальными средствами, чем роль.

У меня есть созданный MethodSecurityExpressionHandler, но я не могу понять, как получить доступ к одному из моих @Services в нем.

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

}

person user2141969    schedule 23.08.2016    source источник


Ответы (1)


Создайте установщик для вашего RepositoryService в CustomMethodSecurityExpressionRoot.

Переопределите setApplicationContext в CustomMethodSecurityExpressionHandler, чтобы передать applicationContext на доступном уровне.

В createSecurityExpressionRoot с помощью applicationContext передать bean-компонент RepositoryService из вашего контекста. Код ниже. Также обратите внимание на изменения, которые я внес в createExpressionHandler() и expressionHandler(). При создании ExpressionHandler вы вызываете супер, который просто использует реализацию по умолчанию, а не объект, который вы только что создали двумя строками ранее. В expressionHandler() вы создаете новый экземпляр CustomMethodSecurityExpressionHandler(), не извлекая тот, который вы создаете в 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;
    }
}
person Billy Korando    schedule 23.08.2016