【问题标题】:@Autowired in Spring PermissionEvaluatorSpring PermissionEvaluator 中的@Autowired
【发布时间】:2014-03-18 23:33:43
【问题描述】:

首先,我在 Google 上进行了广泛的搜索,虽然看起来应该有一个修复程序,但我无法成功引用 PermissionEvaluator 内部注入的 @Bean

https://jira.springsource.org/browse/SEC-2136?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

在该问题的 cmets 部分,Rob Winch 提供了解决建议

要解决此问题,您可以使用 LazyInitTargetSource 代理您的 permissionEvaluator

话虽如此,我在实现发布的 XML 的基于注释的 JavaConfig 版本时遇到了麻烦。 我正在使用 Spring Boot 1.0.0.BUILD-SNAPSHOT 和 spring-boot-starter-security。

我有一个类来配置方法安全性如下:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {                   

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {

        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new MyPermissionEvaluator());
        expressionHandler.setParameterNameDiscoverer(new SimpleParameterDiscoverer());

        return expressionHandler;
    }
}

还有PermissionEvaluator的开头:

public class MyPermissionEvaluator implements PermissionEvaluator {

    private static final Logger LOG = LoggerFactory.getLogger(MyPermissionEvaluator.class); 

    @Autowired
    private UserRepository userRepo;    

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {     

    if (authentication == null || !authentication.isAuthenticated()) {
        return false;
    }

    if (permission instanceof String) {

        switch((String) permission) {

        case "findUser":
            return handleUserPermission(authentication, targetDomainObject);

        default:
            LOG.error("No permission handler found for permission: " + permission);             
        }           
    }

    return false;
}

@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {

    throw new RuntimeException("Id-based permission evaluation not currently supported.");
}

private boolean handleUserPermission(Authentication auth, Object targetDomainObject) {

    if (targetDomainObject instanceof Long) {           

        boolean hasPermission = userRepo.canFind((Long) targetDomainObject);

        return hasPermission;
    }

    return false;
}

}

需要做什么才能从PremissionEvaluator 中获得对我的UserRepository 的引用?我尝试了各种解决方法,但都没有成功。好像没有什么可以把@Autowired变成PermissionEvaluator...

【问题讨论】:

    标签: spring spring-security spring-aop spring-boot


    【解决方案1】:

    没有任何东西可以自动装配到使用new ...() 创建的对象中(除非您使用@Configurable 和AspectJ)。因此,您几乎可以肯定需要将您的PermissionEvaluator 拉到@Bean 中。如果您还需要使其成为惰性代理(因为 Spring Security 初始化的排序敏感性),那么您应该添加 @Lazy @Scope(proxyMode=INTERFACES)(或 TARGET_CLASS,如果更适合您)。

    【讨论】:

    • 这很有道理。我将在今天早上修改代码并回复!谢谢!
    • 嗨 Dave Syer,我遇到了同样的问题。您能否详细解释一下如何在 java 注释中配置“您几乎肯定需要将 PermissionEvaluator 拉出到 @Bean”和“因为 Spring Security 初始化的排序敏感性”,谢谢
    【解决方案2】:

    我遇到了同样的问题,Dave Syer 的回答对我来说非常有效。为了回应来自 jasonfungsing 的评论,将 PermissionEvaluator 拉入一个 Bean,我用 @Component 和 @Autowired 将 DAO 注释到我的自定义类中:

    @Component
    public class CustomPermissionEvaluator implements PermissionEvaluator{
    
    private CustomRepository customRepository;
    
    @Autowired
    public void setCustomRepository(CustomRepository customRepository) {
        this.customRepository = customRepository;
    }
    
    @Override
    public boolean hasPermission(Authentication authentication, Object target, Object permission) {
    
        if (target instanceof ...
    

    然后在我的 GlobalMethodSecurityConfiguration 覆盖类中,我创建了我的 PermissionEvaluator 类的私有实例变量,@Autowired 将 PermissionEvaluator 放入其中并在我的 setPermissionEvaluator 方法调用中使用了这个实例(从而避免了“新”调用):

    @Configuration
    @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
    public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{
    
    private DataSource datasource;
    private CustomPermissionEvaluator customPermissionEvaluator;
    
    @Autowired
    public void setCustomPermissionEvaluator(CustomPermissionEvaluator customPermissionEvaluator) {
        this.customPermissionEvaluator = customPermissionEvaluator;
    }    
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(customPermissionEvaluator);
        return expressionHandler;
    }
    

    我不需要使用@LAZY 或@SCOPE 注释。

    【讨论】:

      【解决方案3】:

      Dave Syer 和 SchonWieder 的解决方案适合我。作为替代方案,我想展示一下我之前是如何解决这个问题的。我像匿名类一样在 MethodSecurityConfig 中注入 Permision Evaluator。

      @Configuration
      @EnableGlobalMethodSecurity(prePostEnabled = true)
      public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{
      
          @Autowired DataSource dataSource;
      
          @Override    
          protected MethodSecurityExpressionHandler createExpressionHandler() {
             DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
             expressionHandler.setPermissionEvaluator(new PermissionEvaluator(){
      
                  @Override
                  public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) {
                          
                          JdbcTemplate template = new JdbcTemplate(dataSource);
                          ... 
                          if (count==1){
                              return true;
                          } else {
                              return false;            
                          }
                      }
      
                  @Override
                  public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3) {
                          // TODO Auto-generated method stub
                          return false;
                      }
                      
                  });
                  return expressionHandler;
              }
      }
      
        

      【讨论】:

        【解决方案4】:

        对于未来的用户:

        根据@Dave Syer 的建议问题是使用 new 关键字将 new MyPermissionEvaluator() 更改为 @Autowired 将解决问题,如下所示。

        修改下面的代码

        发件人:

        @Configuration
        @EnableGlobalMethodSecurity(prePostEnabled = true)
        public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {                   
        
            @Override
            protected MethodSecurityExpressionHandler createExpressionHandler() {
        
                DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
                expressionHandler.setPermissionEvaluator(new MyPermissionEvaluator());
                expressionHandler.setParameterNameDiscoverer(new SimpleParameterDiscoverer());
        
                return expressionHandler;
            }
        }
        

        收件人:

        @Configuration
        @EnableGlobalMethodSecurity(prePostEnabled = true)
        public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 
        
         @Autowired
         private MyPermissionEvaluator myPermissionEvaluator;
        
            @Override
            protected MethodSecurityExpressionHandler createExpressionHandler() {
        
                DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
                expressionHandler.setPermissionEvaluator(myPermissionEvaluator);
                expressionHandler.setParameterNameDiscoverer(new SimpleParameterDiscoverer());
        
                return expressionHandler;
            }
        }
        

        通过上述更改,以下代码将按预期开始工作。

        @Autowired
            private UserRepository userRepo;
        

        【讨论】:

        • 只是添加,你仍然需要用@Component注释你的评估器类
        猜你喜欢
        • 2020-09-24
        • 1970-01-01
        • 1970-01-01
        • 2020-05-22
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 2014-12-15
        • 2012-01-08
        相关资源
        最近更新 更多