1. введение
В этом уроке мы увидим, как мы можем настроить Spring Security для работы с двумя разными страницами входа используя два разных элемента Spring Security http в конфигурации.
2. Настройка 2 Элементов Http
Одна из ситуаций, в которой нам могут понадобиться две страницы входа, – это когда у нас есть одна страница для администраторов приложения и другая страница для обычных пользователей.
Мы настроим два http элемента , которые будут различаться по шаблону URL, связанному с каждым:
- /user* для страниц, для доступа к которым потребуется обычная аутентификация пользователя
- /admin* для страниц, к которым будет обращаться администратор
Каждый элемент http будет иметь другую страницу входа и другой URL-адрес обработки входа.
Чтобы настроить два разных элемента http , давайте создадим два статических класса с аннотациями @Configuration , которые расширяют WebSecurityConfigurerAdapter .
Оба будут помещены в обычный класс @Configuration :
@Configuration @EnableWebSecurity public class SecurityConfig { ... }
Давайте определим WebSecurityConfigurerAdapter для “АДМИНИСТРАТОРА” пользователей:
@Configuration @Order(1) public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter { public App1ConfigurationAdapter() { super(); } @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/admin*") .authorizeRequests() .anyRequest() .hasRole("ADMIN") .and() .formLogin() .loginPage("/loginAdmin") .loginProcessingUrl("/admin_login") .failureUrl("/loginAdmin?error=loginError") .defaultSuccessUrl("/adminPage") .and() .logout() .logoutUrl("/admin_logout") .logoutSuccessUrl("/protectedLinks") .deleteCookies("JSESSIONID") .and() .exceptionHandling() .accessDeniedPage("/403") .and() .csrf().disable(); } }
А теперь давайте определим WebSecurityConfigurerAdapter для обычных пользователей:
@Configuration @Order(2) public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter { public App2ConfigurationAdapter() { super(); } protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/user*") .authorizeRequests() .anyRequest() .hasRole("USER") .and() .formLogin() .loginPage("/loginUser") .loginProcessingUrl("/user_login") .failureUrl("/loginUser?error=loginError") .defaultSuccessUrl("/userPage") .and() .logout() .logoutUrl("/user_logout") .logoutSuccessUrl("/protectedLinks") .deleteCookies("JSESSIONID") .and() .exceptionHandling() .accessDeniedPage("/403") .and() .csrf().disable(); } }
Обратите внимание, что, помещая аннотацию @Order в каждый статический класс, мы указываем порядок, в котором два класса будут рассматриваться на основе сопоставления шаблонов при запросе URL-адреса.
Два класса конфигурации не могут иметь одинаковый порядок.
3. Пользовательские Страницы Входа В Систему
Мы создадим ваши собственные страницы входа для каждого типа пользователей. Для пользователя-администратора форма входа в систему будет иметь действие “user_login” , как определено в конфигурации:
User login page
Страница входа администратора аналогична, за исключением того, что форма будет иметь действие “admin_login” в соответствии с конфигурацией java.
4. Конфигурация аутентификации
Теперь нам нужно настроить аутентификацию для нашего приложения . Давайте рассмотрим два способа достижения этой цели — один с использованием общего источника для аутентификации пользователей, а другой с использованием двух отдельных источников.
4.1. Использование общего источника аутентификации пользователя
Если обе страницы входа имеют общий источник для аутентификации пользователей, вы можете создать один компонент типа UserDetailsService , который будет обрабатывать аутентификацию.
Давайте продемонстрируем этот сценарий с помощью InMemoryUserDetailsManager , который определяет двух пользователей — одного с ролью “ПОЛЬЗОВАТЕЛЬ” и одного с ролью “АДМИНИСТРАТОР” :
@Bean public UserDetailsService userDetailsService() throws Exception { InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(User .withUsername("user") .password(encoder().encode("userPass")) .roles("USER") .build()); manager.createUser(User .withUsername("admin") .password(encoder().encode("adminPass")) .roles("ADMIN") .build()); return manager; } @Bean public static PasswordEncoder encoder() { return new BCryptPasswordEncoder(); }
4.2. Использование Двух Разных Источников Аутентификации Пользователей
Если у вас есть разные источники для аутентификации пользователей — один для администраторов и один для обычных пользователей, — вы можете настроить AuthenticationManagerBuilder внутри каждого статического @Configuration класса. Давайте рассмотрим пример менеджера аутентификации для пользователя “АДМИНИСТРАТОР” :
@Configuration @Order(1) public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("admin") .password(encoder().encode("admin")) .roles("ADMIN"); } }
В этом случае компонент UserDetailsService из предыдущего раздела больше не будет использоваться.
6. Заключение
В этом кратком руководстве мы показали, как реализовать две разные страницы входа в одно и то же приложение Spring Security.
Полный код этой статьи можно найти в проекте GitHub .
При запуске приложения вы можете получить доступ к приведенным выше примерам по /защищенным ссылкам URI.