@Autowired in Spring PermissionEvaluator

时间:2014-02-18 22:32:12

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

首先,我已经广泛搜索了这一点,虽然似乎有一个固定的地方我无法成功引用@Bean内注入的PermissionEvaluator

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

在该问题的评论部分,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;
}

}

我需要做什么才能从UserRepository内部获得对PremissionEvaluator的引用?我尝试了各种变通方法,但没有成功。 @Autowired ......

似乎没有PermissionEvaluator

4 个答案:

答案 0 :(得分:9)

无法将任何内容自动装入使用new ...()创建的对象中(除非您使用@Configurable和AspectJ)。因此,您几乎肯定需要将PermissionEvaluator拉出@Bean。如果你还需要使它成为一个惰性代理(因为Spring Security初始化的排序敏感性),那么你应该添加@Lazy @Scope(proxyMode=INTERFACES)(或TARGET_CLASS,如果这更适合你)。

答案 1 :(得分:7)

我有同样的问题,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类的私有实例变量,@ Perutired PermissionEvaluator并在我的setPermissionEvaluator方法调用中使用了这个实例(因此避免了" new"调用):

@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注释。

答案 2 :(得分:0)

Dave Syer& Sons的解决方案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;
        }
}

  

答案 3 :(得分:0)

对于未来的用户:

根据@Dave Syer的建议问题,使用 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;