Spring安全:使用数据库中的角色登录

问题描述 投票:1回答:1

我在数据库中有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。我该如何告诉SpringROLE表的role_name列中查找用户的角色?

java spring spring-boot spring-security authorization
1个回答
0
投票

是否正常?

不,您在.authoritiesByUsernameQuery方法争论中有错误的查询字符串。

查询返回类型,即结果集应为用户名,角色为SELECT username, role

如果加入查询将导致结果集列名,如下所示。enter image description here您应该将其修改为如下所示enter image description here通过使用别名SELECT ud.username AS username, rm.name AS role

我已经尝试过:antMatchers(“ / mypage”)。hasRole(“ MODERATOR”)但它抛出403错误

因为您的授权部分不正确,所以将不起作用。

我应该如何告诉Spring从ROLE表的role_name列中查找用户的角色?

它需要完整配置身份验证和授权。相同的请参考下面。


我将给出一个工作示例。考虑您的要求具有类似的三个表userdetailsrolemasteruser_role_mapping,如下所示。

enter image description here

然后您的配置将是

@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.
© www.soinside.com 2019 - 2024. All rights reserved.