如何使用DelegatingPasswordEncoder与jdbcAuthentication?

20 浏览
0 Comments

如何使用DelegatingPasswordEncoder与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默认设置,那么就会出现角色问题。

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

我确定我按照Spring的建议进行了数据库和模式的配置(以便能够使用默认的jdbc身份验证)。

在调试模式下,我可以看到从数据库加载的结果在

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错误的配置。

我花了很多时间来调查细节,我的想法已经用尽了。

您认为我需要在构建中添加一些缓存库或其他东西吗?

0
0 Comments

在使用`jdbcAuthentication`时,会出现以下问题的原因是:

1. 使用`hasRole('ADMIN')`时,首先会检查角色是否以角色前缀(默认为`ROLE_`)开头,如果不是,则会将传入的角色添加前缀(参考参考指南)。因此,在这种情况下,实际检查的权限是`ROLE_ADMIN`,而不是你期望/假设的`ADMIN`。

2. 使用内存选项时,`roles`方法也会进行相同的操作。它会检查传入的角色是否以角色前缀开头,如果不是,则会添加前缀。因此,在你的示例中,使用内存选项时,你最终会得到权限`ROLE_ADMIN`和`ROLE_DBA`。

然而,在使用JDBC选项时,你的权限是`ADMIN`和`DBA`,因此`hasRole('ADMIN')`检查失败,因为`ROLE_ADMIN`不等于`ADMIN`。

要解决这个问题,你有几个选择:

1. 代替使用`hasRole`,使用`hasAuthority`,后者不会添加角色前缀。对于内存选项,请使用`authorities`代替`roles`。

2. 在数据库中将权限添加前缀`ROLE_`。

3. 将默认角色前缀设置为空。

使用`hasAuthority`的方法如下:

首先,更改内存数据库的配置,使用`authorities`代替`roles`:

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 {
    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;
    }
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;
    }
    public int getOrder() {
        return PriorityOrdered.HIGHEST_PRECEDENCE;
    }
}

0
0 Comments

问题的原因是因为在使用DelegatingPasswordEncoder进行jdbcAuthentication时,出现了一些错误。通过在application.properties文件中添加日志记录,可以查看发生了什么。

解决方法是添加以下代码到application.properties文件中,以启用日志记录:

# ==============================================================
# = 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

这样做可以将org.springframework.jdbc、org.springframework.security、org.springframework.web和org.springframework.http的日志级别设置为DEBUG。这将允许我们查看更详细的日志信息,以便确定问题的根本原因。

0