我在数据库中有3个表:USER(login,password)
,ROLE(role_name)
和USER_ROLE_LINK (user_id, role_id)
我想授予具有特定角色的用户访问特定页面的权限。
我有配置安全性的此类:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.usersByUsernameQuery("select login, password, active from USER where login=?")
.authoritiesByUsernameQuery("select ur.user_id, ur.role_id from USER u inner join USER_ROLE_LINK ur on u.id = ur.user_id where u.login=?");
}
}
它工作正常,只有具有至少一个角色的用户才能访问该应用。现在,我想授予具有特定角色的用户对特定页面的访问权限,该怎么做?
我已经尝试过:antMatchers("/mypage").hasRole("MODERATOR")
,但是会抛出403 error
。我该如何告诉Spring
从ROLE
表的role_name
列中查找用户的角色?
是否正常?
不,您在.authoritiesByUsernameQuery
方法争论中有错误的查询字符串。
查询返回类型,即结果集应为用户名,角色为SELECT username, role
如果加入查询将导致结果集列名,如下所示。您应该将其修改为如下所示通过使用别名SELECT ud.username AS username, rm.name AS role
我已经尝试过:antMatchers(“ / mypage”)。hasRole(“ MODERATOR”)但它抛出403错误
因为您的授权部分不正确,所以将不起作用。
我应该如何告诉Spring从ROLE表的role_name列中查找用户的角色?
它需要完整配置身份验证和授权。相同的请参考下面。
userdetails
,rolemaster
和user_role_mapping
,如下所示。然后您的配置将是
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
DataSource dataSource;
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception
{
//If you want to store plain password you can use NoOpPasswordEncoder
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder())
.usersByUsernameQuery("select username, password, enabled from userdetails where userName=?")
.authoritiesByUsernameQuery(
"SELECT ud.username AS username, rm.name AS role FROM user_role_mapping map " +
"INNER JOIN userdetails ud ON map.userId = ud.id " +
"INNER JOIN rolemaster rm ON map.roleId = rm.id where userName = ?");
}
@Override
protected void configure(final HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/resources/**", "/", "/login", "/api/**").permitAll()
.antMatchers("/config/**", "/app/admin/**")
.hasRole("ADMIN")
.antMatchers("/app/user/**")
.hasAnyRole("ADMIN", "USER")
.and().exceptionHandling().accessDeniedPage("/403")
.and().formLogin()
.loginPage("/login")
.usernameParameter("userName").passwordParameter("password")
.defaultSuccessUrl("/app/user/dashboard")
.failureUrl("/login?error=true")
.and().logout()
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.csrf()
.disable();
http.sessionManagement().maximumSessions(1).expiredUrl("/login?expired=true");
}
@Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
}
授权部分。通过对存储在资源文件夹中的诸如javascript和css之类的资源的授权.antMatchers("/resources/**", "/", "/login", "/api/**").permitAll()
对于管理员网址.antMatchers("/config/**", "/app/admin/**").hasRole("ADMIN")
对于可以由多个角色访问的网址.antMatchers("/app/user/**").hasAnyRole("ADMIN", "USER")
和.formLogin()
配置
.usernameParameter("userName").passwordParameter("password")
// Use above line of code if your login form param names are diferent
// than defaults -> "username" "password"
.defaultSuccessUrl("/app/user/dashboard")
// If defaultSuccessUrl not configured then after login success redirects to "/"
异常处理部分
.exceptionHandling().accessDeniedPage("/403")
//If you want custom denied screen to be displayed.