Spring Boot + Spring Security + Hierarchical Roles

Mar*_*rio 11 spring spring-security spring-boot

我试图在我的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:以下是根据您的建议更新的代码,但仍然无效.

小智 9

我刚刚通过这些设置,所以一定会让你现在运行.这是交易:

你带来了这个注释,@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)但没有显示任何使用Pre/Post Authorize/Filter的代码,所以我不知道你是否真的需要它.

  1. 如果您不需要该类/方法级安全性/过滤,那么您需要做的就是:

    @Bean
    public RoleHierarchyImpl roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        return roleHierarchy;
    }
    
    Run Code Online (Sandbox Code Playgroud)

        private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
            DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
            defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
            return defaultWebSecurityExpressionHandler;
        }

http
        .authorizeRequests()
        .expressionHandler(webExpressionHandler())
Run Code Online (Sandbox Code Playgroud)

如果只需要引入角色层次结构,则不必使用自己的accessDecisionManager覆盖.

  1. 如果您还需要类/方法级安全性,即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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    }

我将名称GlobalMethodSecurityConfig命名为这个新类,并将当前的GlobalMethodSecurityConfig类更改为WebSecurityConfig或其他内容,以反映它是Web层的安全设置.

RoleHierarchy在webSecurityConfig中定义bean并在globalMethodSecurityConfig中注入/使用它,但只要不必要地创建2个bean,就可以按照自己喜欢的方式执行.

希望这可以帮助.


hol*_*s83 3

您需要在 Web 表达式投票器上设置角色层次结构。就像是:

DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy);
webExpressionVoter.setExpressionHandler(expressionHandler);
Run Code Online (Sandbox Code Playgroud)

更新:您还可以尝试像这样设置上述表达式处理程序:

http
    .authorizeRequests()
    .expressionHandler(expressionHandler)
    ...
Run Code Online (Sandbox Code Playgroud)