我试图在我的Spring Boot应用程序中设置分层角色但没有成功。我已经完成了互联网上不同地方所说的一切。但是他们都没有能够解决这个问题。
这是我的SecurityConfig类的代码。当我使用具有ROLE_ADMIN的用户登录应用程序时,它应该能够从'/ users'检索数据,但是目前我收到了拒绝访问权限的异常。如果用户具有ROLE_USER凭证,则可以正常工作。任何人都可以帮助我找出失败的原因吗?提前致谢。
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SigpaUserDetailsService userDetailsService;
@Bean
public RoleHierarchyImpl roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
return roleHierarchy;
}
@Bean
public RoleHierarchyVoter roleVoter() {
return new RoleHierarchyVoter(roleHierarchy());
}
@Bean
public DefaultWebSecurityExpressionHandler expressionHandler(){
DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy());
return expressionHandler;
}
@Bean
@SuppressWarnings(value = { "rawtypes" })
public AffirmativeBased accessDecisionManager() {
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
webExpressionVoter.setExpressionHandler(expressionHandler());
decisionVoters.add(webExpressionVoter);
decisionVoters.add(roleVoter());
return new AffirmativeBased(decisionVoters);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.accessDecisionManager(accessDecisionManager())
.expressionHandler(expressionHandler())
.antMatchers("/users/**")
.access("hasRole('ROLE_USER')")
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder registry)
throws Exception {
registry.userDetailsService(userDetailsService);
}
}
更新:以下是根据您的建议更新的代码,但仍然无效。
我刚刚通过这些设置,所以一定会让你现在运行。这是交易:
你带来了这个注释@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
但没有显示任何使用Pre / Post Authorize / Filter的代码,所以我不知道你是否真的需要它。
@Bean
public RoleHierarchyImpl roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
return roleHierarchy;
}
和
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
return defaultWebSecurityExpressionHandler;
}
http
.authorizeRequests()
.expressionHandler(webExpressionHandler())
如果只需要引入角色层次结构,则不必使用自己的accessDecisionManager覆盖。
PreAuthorize, PostAuthorize, PreFilter, PostFilter
,那么还要在类路径中创建这样的@Configuration(并从GlobalMethodSecurityConfig类中删除@EnableGlobalMethodSecurity批注):
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class AnyNameYouLike extends GlobalMethodSecurityConfiguration {
@Resource
private RoleHierarchy roleHierarchy;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = (DefaultMethodSecurityExpressionHandler) super.createExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy);
return expressionHandler;
}
}我将名称GlobalMethodSecurityConfig命名为这个新类,并将当前的GlobalMethodSecurityConfig类更改为WebSecurityConfig或其他内容,以反映它是Web层的安全设置。
我在webSecurityConfig中定义了RoleHierarchy
bean并在globalMethodSecurityConfig中注入/使用它,但是你可以以任何你喜欢的方式执行它,只要你不必要地创建2个bean。
希望这可以帮助。
您需要在Web表达式选举器上设置角色层次结构。就像是:
DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy);
webExpressionVoter.setExpressionHandler(expressionHandler);
更新:你也可以尝试设置上面的表达式处理程序,如下所示:
http
.authorizeRequests()
.expressionHandler(expressionHandler)
...
您必须在MethodSecurityExpressionHandler上设置角色层次结构:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Autowired
private RoleHierarchy roleHierarchy;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
final DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
handler.setRoleHierarchy(this.roleHierarchy);
return handler;
}
}
查看Javadoc for @EnableGlobalMethodSecurity以获取更多信息。特别注意:EnableGlobalMethodSecurity仍然必须包含在扩展GlobalMethodSecurityConfiguration的类中以确定设置。
启用方法级安全性(即@EnableGlobalMethodSecurity(prePostEnabled = true))以及在WebSecurityConfigurerAdapter上支持Hierarchical-role。
1.只需要在任何其他使用@Bean注释的类上分离RoleHierarchy 2.在WebSecurityConfigurerAdapter上使用@Autowired注入它。它在我的项目上完美运作。
请查看我的代码。
WebSecurityConfig.class
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private RoleHierarchy roleHierarchy;
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy);
return defaultWebSecurityExpressionHandler;
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/static/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.expressionHandler(webExpressionHandler())
.antMatchers("/static/**","/bower_components/**","/").permitAll()
.antMatchers("/user/login","/user/login?error").anonymous()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/user/login").passwordParameter("password").usernameParameter("username")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout().logoutUrl("/user/logout")
.logoutSuccessUrl("/user/login?logout")
.and().csrf();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
public DaoAuthenticationProvider daoAuthenticationProvider(){
final DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userDetailService);
auth.setPasswordEncoder(passwordEncoder);
return auth;
}
}
BeanConfiguration.class
@Configuration
public class BeanConfiguration {
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
/* tricks lies here */
roleHierarchy.setHierarchy("ROLE_SUPREME > ROLE_ADMIN ROLE_ADMIN > ROLE_OPERATOR ROLE_OPERATOR > ROLE_GUEST");
return roleHierarchy;
}
}
希望它能帮到你。