java - Spring 4 - 带有服务的自定义 SecurityExpression

标签 java spring spring-security spring-rest

在我的一个 Controller 中,我需要使用比角色更细粒度的方法来保护方法。

我创建了一个 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;
    }

}

最佳答案

在 CustomMethodSecurityExpressionRoot 中为您的 RepositoryService 创建一个 setter

覆盖 CustomMethodSecurityExpressionHandler 中的 setApplicationContext,使您传入的 applicationContext 处于可访问级别。

在使用 applicationContext 的 createSecurityExpressionRoot 中,从您的上下文中传入 RepositoryService bean。代码如下。另请注意我对 createExpressionHandler() 和 expressionHandler() 所做的更改。在 create ExpressionHandler 中,您调用的是仅使用默认实现的 super,而不是您之前两行刚刚更新的对象。在 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;
    }
}

关于java - Spring 4 - 带有服务的自定义 SecurityExpression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39090783/

相关文章:

Java导入使用左侧通配符替代?

java - 如何在 Spring MVC 中定义请求映射的优先级?

java - 提交表单时出错-客户端发送的请求在语法上不正确-Spring DAO

exception-handling - spring异常处理程序不处理某些类型的异常

java - 自定义 Spring Oauth 错误

java - @JsonValue 在枚举字段上,当此枚举用作映射键时

java - Liquibase 在执行变更集之前检查表名称长度

java - 使用 MOM 的 Java Spring 微服务示例

javascript - 为什么我的 Controller 中的保存功能不起作用?

android - 使用 Google + Facebook 登录的 Android 应用程序的 Spring boot REST api 安全性