Spring安全性jdbcAuthentication不适用于默认角色处理

运用

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");

我的例子很好.例如

      http.authorizeRequests()
        // ...
        .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
        .and().formLogin()
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");

如果我已将inMemoryAuthentication更改为spring jdbc default – 我遇到了一个角色问题.

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.jdbcAuthentication().dataSource(dataSource);

我确定我使用spring建议配置了db和schema(以便能够使用默认的jdbc身份验证).

在调试模式下,我可以看到从db中加载的结果

org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl
    #loadUserByUsername(username)[line 208]
    return createUserDetails(username, user, dbAuths);

它在内存配置中返回类似的结果:

org.springframework.security.core.userdetails.User@183a3:
     Username: dba;
     Password: [PROTECTED];
     Enabled: true;
     AccountNonExpired: true;
     credentialsNonExpired: true;
     AccountNonLocked: true;
     Granted Authorities: ADMIN,DBA

正如您所看到的,它加载了授权授权,但http请求将我重定向到.accessDeniedPage(“/ Access_Denied”).我感到困惑,因为它应该像以前一样为用户工作.

我不在我的项目中使用spring boot.
我的日志不包含任何jdbc错误配置.
我花了很多时间来调查细节,我的想法刚刚完成.
你认为我需要添加来构建一些缓存库或其他东西吗?

这里有2个陷阱.

第一个是当使用hasRole(‘ADMIN’)时,如果它以角色前缀(默认为ROLE_)开始,则首先进行检查,否则传入的角色是前缀(参见reference guide).因此,在这种情况下,检查的实际权限是ROLE_ADMIN而不是您期望/假设的ADMIN.

第二个是当使用in memory选项时,roles方法与此处提到的相同.它检查传入的角色是否以角色前缀开头,如果没有,则添加它.因此,在具有内存的示例中,您最终会获得权限ROLE_ADMIN和ROLE_DBA.

但是,在JDBC选项中,您具有ADMIN和DBA权限,因此hasRole(‘ADMIN’)检查失败,因为ROLE_ADMIN不等于ADMIN.

要修复你有几个选择.

>而不是hasRole使用hasAuthority,后者不添加角色前缀,而内存选项使用权限而不是角色.
>在JDBC选项前缀中使用ROLE_的数据库中的权限
>将默认角色前缀设置为空.

使用hasAuthority

首先更改内存数据库的配置以使用权限而不是角色.

auth.inMemoryAuthentication()
    .withUser("dba").password("root123")
    .authorities("ADMIN","DBA");

接下来也改变你的表达方式

.antMatchers("/db/**").access("hasAuthority('ADMIN') and hasAuthority('DBA')")

带ROLE_的前缀

在插入权限的脚本中,使用ROLE_作为权限的前缀.

删除默认角色前缀

这有点棘手,并在[迁移指南]中进行了详细描述.

没有简单的配置选项,需要BeanPostProcessor.

public class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {

        // remove this if you are not using JSR-250
        if(bean instanceof Jsr250MethodSecurityMetadataSource) {
            ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null);
        }

        if(bean instanceof DefaultMethodSecurityExpressionHandler) {
            ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
        }
        if(bean instanceof DefaultWebSecurityExpressionHandler) {
            ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
        }
        if(bean instanceof SecurityContextHolderAwareRequestFilter) {
            ((SecurityContextHolderAwareRequestFilter)bean).setRolePrefix("");
        }
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;
    }

    @Override
    public int getOrder() {
        return PriorityOrdered.HIGHEST_PRECEDENCE;
    }
}
https://stackoverflow.com/questions/35894206/spring-security-jdbcauthentication-does-not-work-with-default-roles-processing

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:Spring安全性jdbcAuthentication不适用于默认角色处理