Spring security jdbcAuthentication不适用于默认角色处理

Spring security jdbcAuthentication不适用于默认角色处理,spring,security,authentication,jdbc,role,Spring,Security,Authentication,Jdbc,Role,使用 我的例子很好用。例如 @Autowired public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA"); 如果我已经将inMemoryAuthentication更

使用

我的例子很好用。例如

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
如果我已经将inMemoryAuthentication更改为SpringJDBC默认值,那么我会遇到一个角色问题

      http.authorizeRequests()
        // ...
        .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
        .and().formLogin()
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");
我确信我使用spring建议配置了db和schema(以便能够使用默认的jdbc身份验证)

在调试模式下,我可以在

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.jdbcAuthentication().dataSource(dataSource);
它返回与内存配置类似的结果:

org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl
    #loadUserByUsername(username)[line 208]
    return createUserDetails(username, user, dbAuths);
如您所见,它加载了相应的授权,但http请求将我重定向到.accessDeniedPage(“/Access\u Denied”)。我很困惑,因为它应该像以前一样适用于用户

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

这里有两个陷阱

第一个是,当使用
hasRole('ADMIN')
时,首先检查它是否以角色前缀开头(默认为
role_u
),如果传入的角色不是以它为前缀(另请参见)。因此,在这种情况下,检查的实际权限是
ROLE\u ADMIN
,而不是您期望/假设的
ADMIN

第二个是,当使用内存选项时,
roles
方法的作用与这里提到的相同。它检查传入的角色是否以角色前缀开头,如果不是,则添加它。因此,在内存中的示例中,您最终获得了权限
ROLE\u ADMIN
ROLE\u DBA

但是,在JDBC选项中,您拥有权限
ADMIN
DBA
,因此
hasRole('ADMIN')
检查失败,因为
ROLE\u ADMIN
不等于
ADMIN

要修复此问题,您有几个选项

  • 使用
    hasAuthority
    代替
    hasRole
    ,后者不添加角色前缀,对于内存选项,使用
    Authority
    代替
    roles
  • 在JDBC选项中,在数据库中的权限前面加上
    ROLE\uuu
  • 将默认角色前缀设置为空 使用
    hasAuthority
    首先更改内存数据库的配置,以使用
    权限
    而不是
    角色

    org.springframework.security.core.userdetails.User@183a3:
         Username: dba;
         Password: [PROTECTED];
         Enabled: true;
         AccountNonExpired: true;
         credentialsNonExpired: true;
         AccountNonLocked: true;
         Granted Authorities: ADMIN,DBA
    
    下一步也要改变你的表情

    auth.inMemoryAuthentication()
        .withUser("dba").password("root123")
        .authorities("ADMIN","DBA");
    
    前缀为
    角色
    在插入权限的脚本中,将权限前缀为
    角色

    删除默认角色前缀 这有点棘手,在[迁移指南]中有详细描述

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

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

    您可以看到启用日志记录时发生了什么。在
    应用程序.properties中添加:

    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;
        }
    }
    

    不,不应该。。。当使用in-memroy数据库时,角色会自动以
    ROLE_uu
    作为前缀(默认角色前缀)。这同样适用于
    hasRole('ADMIN')
    ,它还将检查传入的角色是否有前缀,如果没有前缀,将添加该角色。您的用户拥有权限
    ADMIN
    而不是
    ROLE\u ADMIN
    ,因此检查失败。使用
    hasAuthority
    而不是
    hasRole
    (并在内存样本中将
    roles
    更改为
    authorities
    ),或者在数据库中的权限前面加上
    ROLE\uu
    前缀,或者将默认角色前缀改为空而不是
    ROLE\uu
    。非常感谢!现在可以了。你能在角色比较的地方添加链接吗(我希望这些信息在不久的将来对我有用)?
    # ==============================================================
    # = Logging springframework
    # ==============================================================
    logging.level.org.springframework.jdbc=DEBUG
    logging.level.org.springframework.security=DEBUG
    logging.level.org.springframework.web=DEBUG
    logging.level.org.springframework.http=DEBUG