Spring security: вход с использованием ролей из базы данных - PullRequest
1 голос
/ 06 октября 2019

У меня есть 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 столбца?

1 Ответ

1 голос
/ 06 октября 2019

Работает нормально?

Нет, у вас неверная строка запроса в .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_name таблицы ROLE?

Требуется полная настройка аутентификации и авторизации. См. Ниже для того же.

Я приведу один рабочий пример:

Учтите, что в вашем требовании есть аналогичные три таблицы userdetails, rolemaster и user_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()

Для URL-адресов администратора

.antMatchers("/config/**", "/app/admin/**").hasRole("ADMIN")

Для URL-адресов, к которым могут обращаться несколько ролей

.antMatchers("/app/user/**").hasAnyRole("ADMIN", "USER")

И.formLogin() конфигурация:

.usernameParameter("userName").passwordParameter("password") 
// Use above line of code if your login form param names are different 
// 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.
...