Перейти к основному содержимому

Две страницы входа с Spring Security

· 4 мин. чтения

1. Введение

В этом руководстве мы увидим, как мы можем настроить Spring Security для работы с двумя разными страницами входа , используя два разных http -элемента Spring Security в конфигурации.

2. Настройка 2-х HTTP-элементов

Одна из ситуаций, в которой нам могут понадобиться две страницы входа, — это когда у нас есть одна страница для администраторов приложения и другая страница для обычных пользователей.

Мы настроим два элемента http , которые будут различаться шаблоном URL, связанным с каждым:

  • /user* для страниц, для доступа к которым потребуется обычная аутентификация пользователя.
  • /admin* для страниц, к которым будет обращаться администратор

Каждый элемент http будет иметь другую страницу входа и другой URL-адрес обработки входа.

Чтобы настроить два разных элемента http , давайте создадим два статических класса с аннотацией @Configuration , которые расширяют WebSecurityConfigurerAdapter .

Оба будут помещены в обычный класс @Configuration :

@Configuration
@EnableWebSecurity
public class SecurityConfig {
...
}

Давайте определим WebSecurityConfigurerAdapter для пользователей «ADMIN» :

@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» , как определено в конфигурации:

<p>User login page</p>
<form name="f" action="user_login" method="POST">
<table>
<tr>
<td>User:</td>
<td><input type="text" name="username" value=""></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td><input name="submit" type="submit" value="submit" /></td>
</tr>
</table>
</form>

Страница входа администратора аналогична, за исключением того, что форма будет иметь действие «admin_login» в соответствии с конфигурацией Java.

4. Конфигурация аутентификации

Теперь нам нужно настроить аутентификацию для нашего приложения . Давайте рассмотрим два способа сделать это — один с использованием общего источника для аутентификации пользователя, а другой — с использованием двух отдельных источников.

4.1. Использование общего источника аутентификации пользователя

Если обе страницы входа имеют общий источник для аутентификации пользователей, вы можете создать один bean-компонент типа 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 . Давайте рассмотрим пример диспетчера аутентификации для пользователя «ADMIN» :

@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");
}
}

В этом случае bean-компонент UserDetailsService из предыдущего раздела больше не будет использоваться.

6. Заключение

В этом кратком руководстве мы показали, как реализовать две разные страницы входа в одно и то же приложение Spring Security.

Полный код для этой статьи можно найти в проекте GitHub .

Когда вы запускаете приложение, вы можете получить доступ к приведенным выше примерам по URI /protectedLinks .