Ser*_*gii 4 security authentication spring jdbc role
使用
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
Run Code Online (Sandbox Code Playgroud)
我的例子效果很好。例如对于
http.authorizeRequests()
// ...
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.and().formLogin()
.and().exceptionHandling().accessDeniedPage("/Access_Denied");
Run Code Online (Sandbox Code Playgroud)
如果我将 inMemoryAuthentication 更改为 spring jdbc 默认值 - 我遇到了角色问题。
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
Run Code Online (Sandbox Code Playgroud)
我确信我使用 spring 建议配置了数据库和架构(以便能够使用默认的 jdbc 身份验证)。
在调试模式下,我可以看到从数据库加载的结果
org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl
#loadUserByUsername(username)[line 208]
return createUserDetails(username, user, dbAuths);
Run Code Online (Sandbox Code Playgroud)
它返回与内存配置类似的结果:
org.springframework.security.core.userdetails.User@183a3:
Username: dba;
Password: [PROTECTED];
Enabled: true;
AccountNonExpired: true;
credentialsNonExpired: true;
AccountNonLocked: true;
Granted Authorities: ADMIN,DBA
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它加载了相应的授予权限,但 http 请求将我重定向到.accessDeniedPage("/Access_Denied")。我很困惑,因为它应该像以前一样为用户工作。
我的项目中没有使用 spring boot。我的日志不包含任何 jdbc 错误配置。我花了很多时间去考察细节,我的想法才刚刚完成。你认为我需要添加来构建一些缓存库或其他东西吗?
这里有两个陷阱。
第一个是,当hasRole('ADMIN')首先使用它时,会检查它是否以角色前缀(默认为ROLE_)开头,如果传入的角色不是以它为前缀(另请参阅参考指南)。因此,在这种情况下,检查的实际权限ROLE_ADMIN并不ADMIN像您期望/假设的那样。
第二个是,当使用内存中选项时,该roles方法的作用与此处提到的相同。它检查传入的角色是否以角色前缀开头,如果不是则添加它。因此,在您的内存样本中,您最终会得到权威ROLE_ADMIN和ROLE_DBA。
然而,在您的 JDBC 选项中,您拥有权限ADMIN,DBA因此hasRole('ADMIN')检查失败,因为ROLE_ADMIN不等于ADMIN。
要解决此问题,您有多种选择。
hasRole使用.hasAuthorityauthoritiesrolesROLE_hasAuthority首先将内存数据库的配置更改为authorities使用roles.
auth.inMemoryAuthentication()
.withUser("dba").password("root123")
.authorities("ADMIN","DBA");
Run Code Online (Sandbox Code Playgroud)
接下来也改变一下你的表情
.antMatchers("/db/**").access("hasAuthority('ADMIN') and hasAuthority('DBA')")
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)