如何使用DelegatingPasswordEncoder与jdbcAuthentication?
如何使用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错误的配置。
我花了很多时间来调查细节,我的想法已经用尽了。
您认为我需要在构建中添加一些缓存库或其他东西吗?
在使用`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; } }
问题的原因是因为在使用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。这将允许我们查看更详细的日志信息,以便确定问题的根本原因。