spring security @Secured和HttpSession配置排序

时间:2014-09-17 10:37:57

标签: java spring security spring-security

我正在使用Spring Security(3.2.5.RELEASE)。我尝试实现以下方案:

  1. 我的应用程序中有两种用户:普通用户和管理员
  2. 我想在控制器方法上使用@Secured注释(使用@RequestMapping注释)
  3. 未使用@Secured注释的方法我希望所有人都可以访问(即使是匿名用户)。
  4. 如果常规用户具有传递给@Secured注释的特定角色,则会使用@Secured注释的方法。对于管理员用户,也应始终允许使用这些方法,但我不希望每次使用ROLE_ADMIN注释时都放置@Secured
  5. 这是我的HttpSession配置:

    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers("/**")
                    .permitAll()
         [...] 
        }
    

    我可以使用@Secured注释来注释我的控制器方法,并且它可以正常工作。唯一的问题是如何添加url-intercept matcher以允许所有具有角色ROLE_ADMIN的用户在从@Secured注释方法收集的访问规则之前。目前看起来@Secured方法在过滤器链中排在第一位,而上面代码中添加到HttpSession的规则是最后一个。如何添加首先(ROLE_ADMIN permision)和last(对于所有未使用@Secured permision注释的方法)的规则,@Secured注释中的所有规则都将包含在这些规则中两个规则?为了更清楚,我想实现这样的事情(在链中):

    1) allow all for users with ROLE_ADMIN
    2) all rules from @Secured
    3) allow methods not annotated with @Secured for all
    

1 个答案:

答案 0 :(得分:1)

好的,我已经实现了这一点,但并不完全像问题那样。这就是我所做的:

  1. 创建自己的AccessDecisionVoter,对于admin。
  2. 用户将始终返回ACCESS_GRANTED
  3. 覆盖默认AccessDecisionManager的创建:两个!!!一个用于拦截网址,一个用于拦截方法。
  4. 这是我的AdminPermitVoter

    public class AdminPermitVoter implements AccessDecisionVoter<Object> {
    
        @Override
        public boolean supports(ConfigAttribute attribute) {
            return true;
        }
    
        @Override
        public boolean supports(Class<?> clazz) {
            return true;
        }
    
        @Override
        public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
            if(isAdmin(extractAuthorities(authentication))) {
                return ACCESS_GRANTED;
            }
            return ACCESS_ABSTAIN;
        }
    
        Collection<? extends GrantedAuthority> extractAuthorities(Authentication authentication) {
            return authentication.getAuthorities();
        }
    
        private boolean isAdmin(Collection<? extends GrantedAuthority> authorities) {
            for(GrantedAuthority authority : authorities) {
                if(equalsIgnoreCase(ADMIN_ROLE_NAME, authority.getAuthority())) {
                    return true;
                }
            }
    
            return false;
        }
    }
    

    这是默认url interecption访问决策管理器的创建:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .accessDecisionManager(accessDecisionManager())
                .anyRequest()
                .permitAll()
            [...other configs...]
     }
    
    @Bean(name = "accessDecisionManager")
    public AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter> voters = new ArrayList<>();
        voters.add(new AdminPermitVoter());
        voters.add(new WebExpressionVoter());
        voters.add(new RoleVoter());
        voters.add(new AuthenticatedVoter());
        return new AffirmativeBased(voters);
    }
    

    这是默认方法拦截访问决策管理器的创建:

    @Configuration
    @EnableGlobalMethodSecurity(securedEnabled = true)
    public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    
        @SuppressWarnings("rawtypes")
        @Override
        protected AccessDecisionManager accessDecisionManager() {
            List<AccessDecisionVoter> voters = new ArrayList<>();
            voters.add(new AdminPermitVoter());
            voters.add(new RoleVoter());
            voters.add(new AuthenticatedVoter());
            return new AffirmativeBased(voters);
        }
    
    }