Spring Custom Login Form

В этой статье рассмотрим, как заменить автоматически генерируемую форму ввода имени и пароля на свою собственную на Thymeleaf.

Метод formLogin() генерирует как саму форму логина, так и конечную точку обработки имени и пароля, приходящих с формы. Конечную точку, обрабатывающую по POST-запросу имя и пароль, переписывать не нужно, а вот саму html-форму, выдающуюся по методу GET /login обычно требуется заменить.

Настройка HttpSecurity

Чтобы это сделать, при настройке HttpSecurity нужно указать не просто formLogin(), как мы делали раньше, а еще .loginPage(«/login») с адресом шаблона:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/**").hasRole("USER")
            .and()
            .formLogin().permitAll()
            .loginPage("/login")
            .loginProcessingUrl("/perform-login")
            .usernameParameter("user")
            .passwordParameter("pass")
            .defaultSuccessUrl("/");
}

На адрес /login (указанный в loginPage(), адрес можно указать и другой) необходимо добавить контроллер, который выдает шаблон.

Контроллер

@Controller
public class LoginController {

    @GetMapping("/login")
    public String get(Model model) {
        model.addAttribute("title", "Форма входа");
        return "login";
    }

}

Как видите, мы передали tittle в модель, но это необязательно — его можно сразу прописать в шаблоне.

Шаблон

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <title th:text="${title}"></title>
</head>

<body>
<div>
    <form name="f" th:action="@{/perform-login}" method="post">
        <fieldset>
            <legend>Войдите</legend>
            <div th:if="${param.error}" class="alert alert-error">
                Неправильные имя и пароль.
            </div>

            <div th:if="${param.logout}" class="alert alert-success">
                You have been logged out.
            </div>
            <label for="user">Имя</label>
            <input type="text" id="user" name="user"/>
            <label for="pass">Пароль</label>
            <input type="password" id="pass" name="pass"/>
            <div class="form-actions">
                <button type="submit" class="btn">Войти</button>
            </div>
        </fieldset>
    </form>
</div>
</body>
</html>

Выглядит так:

Пользовательская форма входа
Пользовательская форма входа

В шаблоне обратите внимание на ряд параметров, которые важны для конечной точки, обрабатывающей имя и пароль по POST-запросу.

Во-первых, это имена элементов input — они превращаются в имена параметров POST-запроса.

usernameParameter() и passwordParameter()

В автоматически генерируемой форме они называются username и password, а поскольку у нас это user и pass (см. атрибуты name):

<input type="text" id="user" name="user"/>

<input type="password" id="pass" name="pass"/>

то в коде настройки HttpSecurity мы должны переопределить их в методах:

.usernameParameter("user")
.passwordParameter("pass")

Эти строки есть в первом сниппете.

loginProcessingUrl()

Также переопределен loginProcessingUrl():

.loginProcessingUrl("/perform-login")

Это адрес конечной точки, куда по методу POST отправляются имя и пароль при нажатии кнопки входа. Адрес переопределен, но сама точка осталась автогенерируемой (ее генерирует Spring Security).

В шаблоне этот адрес соответствует action формы:

<form name="f" th:action="@{/perform-login}" method="post">

defaultSuccessUrl()

Наконец, можно задать

.defaultSuccessUrl("/");

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

Обычно он перенаправляется на ту самую закрытую страницу, куда пытался попасть (а после этого был перенаправлен на страницу входа /login).

Но если он не пытался попасть на закрытую страницу, а сразу заходил с /login, то куда-то его надо перенаправить. Вот тут и указывается этот адрес. У нас это главная страница.

Сообщение об ошибке

Наконец, если были введены неправильные имя и пароль, необходимо перенаправить пользователя на страницу с ошибкой. По умолчанию этот тот же адрес /login, но с параметром:

/login?error

В шаблоне есть обработка этого параметра:

<div th:if="${param.error}" class="alert alert-error">
    Неправильные имя и пароль.
</div>

Не стоит пытаться уточнять сообщение (что именно неправильное: имя или пароль). Spring Security рекомендует оставить  все как есть, чтобы злоумышленник не пытался подобрать другое имя — в общем лишней информации тут давать не нужно.

Исходный код

Скачать пример полностью можно на GitHub.

Spring Custom Login Form: 4 комментария

  1. Забыли указать, что для Thymeleaf необходимо указать соответствующую зависимость в pom.xml

  2. Теперь настройка HttpSecurity:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
    .authorizeHttpRequests((auth) ->
    auth
    .requestMatchers(«/**»).hasRole(«USER»)
    )
    .formLogin(login -> login.permitAll()
    .loginPage(«/login»)
    .loginProcessingUrl(«/perform-login»)
    .usernameParameter(«user»)
    .passwordParameter(«pass»)
    .defaultSuccessUrl(«/»));
    return http.build();
    }

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *