Spring Security:AccessDecisionVoter
@Service public class MyVoter implements AccessDecisionVoter { @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 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 beans = context .getBeansOfType(AccessDecisionVoter.class); List decisionVoters = new ArrayList( beans.values()); AffirmativeBased affirmativeBased = new AffirmativeBased(decisionVoters); return affirmativeBased; } }
这基本上是我唯一的配置。
这就是我使用AccessDecisionManager的方式:
/* AUTHORIZATION */ Authentication authentication = SecurityContextHolder.getContext() .getAuthentication(); Collection config = new HashSet(); config.add(new SecurityConfig("Something")); try { adm.decide(authentication, project, config); } catch (Exception e) { // .. Exception Handling }
如果没有Spring安全应用程序上下文配置,很难给出正确答案,但对于您的问题,该方法的Javadoc说明如下:
Indicates whether this AccessDecisionVoter is able to vote on the passed ConfigAttribute.
实际为ConfigAttribute
调用此方法,如下面的"isAnonymous()"
for WebExpressionVoter
或者对于RoleVoter
,例如"ROLE_ADMIN"
WebExpressionVoter
和RoleVoter
都是AccessDecisionVoter
实现。 除非您没有尝试评估上面提到的任何ConfigAttribute
。 永远不会调用您的方法,因此无论您返回true
还是false
都不会看到任何影响。 希望这可以帮助。
编辑
如果你看一下AffirmativeBased AccessDecisionManager的decide
方法。
public void More ...decide(Authentication authentication, Object object, Collection 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 { @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 config) { if(supports(config)) { // Add this check return ACCESS_GRANTED; } else { return ACCESS_DENIED; // Abstain Based on your requirement } } }