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

Вход в форму безопасности Spring

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

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Введение

В этом руководстве основное внимание будет уделено входу в систему с помощью Spring Security . Мы собираемся использовать предыдущий пример Spring MVC , так как это необходимая часть настройки веб-приложения вместе с механизмом входа в систему.

2. Зависимости Maven

При работе с Spring Boot стартер spring-boot-starter-security автоматически включает все зависимости, такие как spring-security-core , spring-security-web и spring-security-config среди прочих:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>

Если мы не используем Spring Boot, см. статью Spring Security with Maven , в которой описано, как добавить все необходимые зависимости. Потребуются как стандартный spring-security-web, так и spring-security-config .

3. Конфигурация Java безопасности Spring

Начнем с создания класса конфигурации Spring Security, который расширяет WebSecurityConfigurerAdapter.

Добавив @EnableWebSecurity , мы получаем поддержку интеграции Spring Security и MVC:

@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
// authentication manager (see below)
}

@Override
protected void configure(final HttpSecurity http) throws Exception {
// http builder configurations for authorize requests and form login (see below)
}
}

В этом примере мы использовали аутентификацию в памяти и определили трех пользователей.

Далее мы рассмотрим элементы, которые мы использовали для создания конфигурации входа в форму.

Давайте начнем с создания нашего диспетчера аутентификации.

3.1. Менеджер аутентификации

Поставщик аутентификации поддерживается простой реализацией в памяти InMemoryUserDetailsManager . Это полезно для быстрого прототипирования, когда полный механизм персистентности еще не нужен:

protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password(passwordEncoder().encode("user1Pass")).roles("USER")
.and()
.withUser("user2").password(passwordEncoder().encode("user2Pass")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder().encode("adminPass")).roles("ADMIN");
}

Здесь мы настроим трех пользователей с жестко закодированным именем пользователя, паролем и ролью.

Начиная с Spring 5, мы также должны определить кодировщик паролей . В нашем примере мы будем использовать BCryptPasswordEncoder:

@Bean 
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Далее давайте настроим HttpSecurity.

3.2. Конфигурация для авторизации запросов

Мы начнем с выполнения необходимых настроек для авторизации запросов.

Здесь мы разрешаем анонимный доступ к /login , чтобы пользователи могли пройти аутентификацию. Мы ограничим / admin ролями ADMIN и защитим все остальное:

@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/anonymous*").anonymous()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()
.and()
// ...
}

Обратите внимание, что порядок элементов antMatchers() имеет значение; более конкретные правила должны идти первыми, а затем более общие .

3.3. Конфигурация для входа в форму

Далее мы расширим приведенную выше конфигурацию для входа и выхода из формы:

@Override
protected void configure(final HttpSecurity http) throws Exception {
http
// ...
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/homepage.html", true)
.failureUrl("/login.html?error=true")
.failureHandler(authenticationFailureHandler())
.and()
.logout()
.logoutUrl("/perform_logout")
.deleteCookies("JSESSIONID")
.logoutSuccessHandler(logoutSuccessHandler());
}
  • loginPage() — пользовательская страница входа
  • loginProcessingUrl() — URL-адрес для отправки имени пользователя и пароля.
  • defaultSuccessUrl() — целевая страница после успешного входа
  • failureUrl() — целевая страница после неудачного входа в систему.
  • logoutUrl() — пользовательский выход

4. Добавьте Spring Security в веб-приложение

Чтобы использовать определенную выше конфигурацию Spring Security, нам нужно прикрепить ее к веб-приложению.

Мы будем использовать WebApplicationInitializer , поэтому нам не нужно предоставлять какой-либо файл web.xml:

public class AppInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext sc) {

AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.register(SecSecurityConfig.class);

sc.addListener(new ContextLoaderListener(root));

sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
}
}

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

5. XML-конфигурация безопасности Spring

Давайте также взглянем на соответствующую конфигурацию XML.

Весь проект использует конфигурацию Java, поэтому нам нужно импортировать файл конфигурации XML через класс Java @Configuration :

@Configuration
@ImportResource({ "classpath:webSecurityConfig.xml" })
public class SecSecurityConfig {
public SecSecurityConfig() {
super();
}
}

И XML-конфигурация Spring Security, webSecurityConfig.xml :

<http use-expressions="true">
<intercept-url pattern="/login*" access="isAnonymous()" />
<intercept-url pattern="/**" access="isAuthenticated()"/>

<form-login login-page='/login.html'
default-target-url="/homepage.html"
authentication-failure-url="/login.html?error=true" />
<logout logout-success-url="/login.html" />
</http>

<authentication-manager>
<authentication-provider>
<user-service>
<user name="user1" password="user1Pass" authorities="ROLE_USER" />
</user-service>
<password-encoder ref="encoder" />
</authentication-provider>
</authentication-manager>

<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
</beans:bean>

6. Веб- файл.xml

До появления Spring 4 мы настраивали Spring Security в файле web.xml; в стандартный Spring MVC web.xml добавлен только дополнительный фильтр :

<display-name>Spring Secured Application</display-name>

<!-- Spring MVC -->
<!-- ... -->

<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Фильтр — DelegatingFilterProxy — просто делегирует управляемый Spring bean-компонент — FilterChainProxy — который сам может извлечь выгоду из полного управления жизненным циклом Spring bean-компонента и тому подобного.

7. Форма входа

Страница формы входа будет зарегистрирована в Spring MVC с использованием простого механизма для сопоставления имен представлений с URL-адресами . Кроме того, нет необходимости в явном промежуточном контроллере:

registry.addViewController("/login.html");

Это, конечно же, соответствует файлу login.jsp :

<html>
<head></head>
<body>
<h1>Login</h1>
<form name='f' action="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>
</body>
</html>

Форма Spring Login имеет следующие соответствующие артефакты:

  • логин — URL-адрес, по которому форма размещается для запуска процесса аутентификации.
  • имя пользователя — имя пользователя
  • пароль - пароль

8. Дальнейшая настройка Spring Login

Мы кратко обсудили несколько конфигураций механизма входа в систему, когда мы представили конфигурацию безопасности Spring выше. Теперь давайте углубимся в некоторые подробности.

Одна из причин переопределить большинство значений по умолчанию в Spring Security — скрыть, что приложение защищено с помощью Spring Security. Мы также хотим свести к минимуму информацию, которую потенциальный злоумышленник знает о приложении.

Полностью настроенный элемент входа выглядит следующим образом:

@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/homepage.html",true)
.failureUrl("/login.html?error=true")
}

Или соответствующая конфигурация XML:

<form-login 
login-page='/login.html'
login-processing-url="/perform_login"
default-target-url="/homepage.html"
authentication-failure-url="/login.html?error=true"
always-use-default-target="true"/>

8.1. Страница входа

Далее мы настроим пользовательскую страницу входа с помощью метода loginPage():

http.formLogin()
.loginPage("/login.html")

Точно так же мы можем использовать конфигурацию XML:

login-page='/login.html'

Если мы не укажем это, Spring Security сгенерирует очень простую форму входа в систему по URL-адресу /login .

8.2. URL-адрес POST для входа

URL-адрес по умолчанию, по которому Spring Login будет выполнять POST для запуска процесса аутентификации, — это /login, который раньше был /j_spring_security_check до Spring Security 4 .

Мы можем использовать метод loginProcessingUrl , чтобы переопределить этот URL:

http.formLogin()
.loginProcessingUrl("/perform_login")

Мы также можем использовать конфигурацию XML:

login-processing-url="/perform_login"

Переопределяя этот URL-адрес по умолчанию, мы скрываем, что приложение на самом деле защищено с помощью Spring Security. Эта информация не должна быть доступна извне.

8.3. Целевая страница об успехе

После успешного входа в систему мы будем перенаправлены на страницу, которая по умолчанию является корнем веб-приложения.

Мы можем переопределить это с помощью метода defaultSuccessUrl() :

http.formLogin()
.defaultSuccessUrl("/homepage.html")

Или с конфигурацией XML:

default-target-url="/homepage.html"

Если для атрибута always-use-default-target установлено значение true, пользователь всегда перенаправляется на эту страницу. Если для этого атрибута установлено значение false, пользователь будет перенаправлен на предыдущую страницу, которую он хотел посетить, прежде чем ему будет предложено пройти аутентификацию.

8.4. Целевая страница при неудаче

Как и страница входа, страница сбоя входа автоматически создается Spring Security по адресу /login? ошибка по умолчанию.

Чтобы переопределить это, мы можем использовать метод failureUrl() :

http.formLogin()
.failureUrl("/login.html?error=true")

Или с XML:

authentication-failure-url="/login.html?error=true"

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

В этом примере Spring Login мы настроили простой процесс аутентификации. Мы также обсудили форму входа в Spring Security, конфигурацию безопасности и некоторые из более сложных доступных настроек.

Реализацию этой статьи можно найти в проекте GitHub — это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.

Когда проект выполняется локально, доступ к образцу HTML можно получить по адресу:

http://localhost:8080/spring-security-mvc-login/login.html