Spring Security:AccessDecisionVoter

时间:2014-07-05 14:44:18

标签: java spring security vote

@Service
public class MyVoter implements AccessDecisionVoter<Entity> {

    @Override
    public boolean supports(ConfigAttribute attribute) {        
        boolean myBool = false;
        return myBool;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz == Project.class;
    }

    @Override
    public int vote(Authentication authentication, Entity someEntity,
            Collection<ConfigAttribute> config) {
        return ACCESS_GRANTED;
    }
}

你能解释一下,第一个支持方法应该如何工作?无论我如何更改myBool,都会调用vote-method。似乎只支持(Class clazz)对invokation有影响。

有什么想法吗?

编辑:

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
ApplicationContext context;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http
        .authorizeRequests()
            .antMatchers("/").permitAll()
            .anyRequest().authenticated();
    http
        .formLogin()
            .loginPage("/login")
            .permitAll()               
            .and()
        .logout()
            .permitAll();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
}

@Bean
public AffirmativeBased accessDecisionManager() {
    Map<String, AccessDecisionVoter> beans = context
            .getBeansOfType(AccessDecisionVoter.class);

    List<AccessDecisionVoter> decisionVoters = new ArrayList<>(
            beans.values());

    AffirmativeBased affirmativeBased = new AffirmativeBased(decisionVoters);
    return affirmativeBased;
}
}

这基本上是我唯一的配置。

这就是我使用AccessDecisionManager的方式:

    /* AUTHORIZATION */
    Authentication authentication = SecurityContextHolder.getContext()
            .getAuthentication();

    Collection<ConfigAttribute> config = new HashSet<ConfigAttribute>();
    config.add(new SecurityConfig("Something"));

    try {
        adm.decide(authentication, project, config);
    } catch (Exception e) {
        // .. Exception Handling
    }

1 个答案:

答案 0 :(得分:3)

如果没有Spring安全应用程序上下文配置,很难给出正确答案,但对于您的问题,该方法的Javadoc说明如下:

Indicates whether this AccessDecisionVoter is able to vote on the 
passed ConfigAttribute.

ConfigAttribute实际调用此方法,例如以下"isAnonymous()" WebExpressionVoter

<security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/login*"
            access="isAnonymous()" />
</security:http>

RoleVoter"ROLE_ADMIN"

<security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/admin/**"
            access="ROLE_ADMIN" />
</security:http>

WebExpressionVoterRoleVoter都是AccessDecisionVoter的实现。除非您没有尝试评估上面提到的任何ConfigAttribute。永远不会调用您的方法,因此,无论您是返回true还是false,都不会看到任何效果。希望这会有所帮助。

修改

如果您查看AffirmativeBased AccessDecisionManager的decide方法。

public void More ...decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
46            throws AccessDeniedException {
47        int deny = 0;
48
49        for (AccessDecisionVoter voter : getDecisionVoters()) {
50            int result = voter.vote(authentication, object, configAttributes);
51
52            if (logger.isDebugEnabled()) {
53                logger.debug("Voter: " + voter + ", returned: " + result);
54            }
55
56            switch (result) {
57            case AccessDecisionVoter.ACCESS_GRANTED:
58                return;
59
60            case AccessDecisionVoter.ACCESS_DENIED:
61                deny++;
62
63                break;
64
65            default:
66                break;
67            }
68        }
69
70        if (deny > 0) {
71            throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
72                    "Access is denied"));
73        }
74
75        // To get this far, every AccessDecisionVoter abstained
76        checkAllowIfAllAbstainDecisions();
77    }

根本没有使用supports(ConfigAttribute con)方法。因此,您必须修改您的编码,以便检查如下工作。

@Service
public class MyVoter implements AccessDecisionVoter<Entity> {

    @Override
    public boolean supports(ConfigAttribute attribute) {        
        boolean myBool = false;
        return myBool;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz == Project.class;
    }

    @Override
    public int vote(Authentication authentication, Entity someEntity,
            Collection<ConfigAttribute> config) {
        if(supports(config)) { // Add this check
            return ACCESS_GRANTED;
        } else {
            return ACCESS_DENIED; // Abstain Based on your requirement
        }
    }
}