CSRF / Spring Security - ошибка 403 после входа в систему через AJAX - PullRequest
0 голосов
/ 26 марта 2019

Я столкнулся с проблемой при использовании защиты CSRF в Spring Security 5.1.4.

Я настроил пользовательскую страницу входа в приложение.Когда пользователь вводит свои учетные данные, выполняется запрос AJAX.Обработчик успеха выполняет свои обязанности и возвращает в ответ документ JSON.После успешного вызова AJAX экран динамически обновляется, удаляя поля имени пользователя и пароля и заменяя их на раскрывающееся поле и кнопку «Продолжить».

Когда пользователь делает выбор из раскрывающегося списка и нажимает кнопку «Продолжить»действие в форме изменяется, и форма отправляется с использованием метода POST.Затем пользователь должен быть направлен на домашний экран.К сожалению, приложение отвечает ошибкой Forbidden (403).

Когда я изменяю WebSecurityConfigurerAdapter, чтобы отключить защиту CSRF, мой экран входа в систему работает должным образом.

Есть ли что-то, что мне не хватает, когдаЯ отправляю форму?Обратите внимание, что я включил параметр CSRF и токен в скрытое поле внутри элемента формы.

WebSecurityConfigurerAdapter

protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/images/**", "/js/**")
                .permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .successHandler(customAuthenticationHandler)
                .permitAll()
                .and()
                .logout()
                .invalidateHttpSession(true)
                .deleteCookies("JESSIONID")
                .permitAll();
    }

public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
}

Контроллер

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String logIn() {
    return "login-custom";
}

@RequestMapping(value = "/home", method = RequestMethod.POST)
public String home() {
    return "home";
}

JSP

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title></title>

    <script type="text/javascript" src="/workdaybsa/js/jquery-1.10.2.min.js"></script>
    <script language="javascript">

        function login() {
            $.ajax({
                url: $('#loginForm').attr('action'),
                type: 'POST',
                data: $('#loginForm').serialize(),
                dataType: "json",
                success: function(response){
                    $('#loginSection').attr('style', 'display:none');
                    $('#selectionSection').removeAttr('style');
                },
                error: function (xhr, status, error) {
                    alert(status);
                    alert(error);
                }
           });
        }

        function proceed() {
            $('form').attr('action', 'home');
            $('form').submit();
        }
    </script>

</head>

<body>

    <form id="loginForm" action="login" method="post">

        <div id="loginSection">
            <p>
                <label for="username">Username</label>
                <input type="text" id="username" name="username">
            </p>
            <p>
                <label for="password">Password</label>
                <input type="password" id="password" name="password">
            </p>
            <input type="button" value="Sign In" onclick="login()">
        </div>
        <div id="selectionSection" style="display:none">
            <select id="selection">
                <option value="">-- Select The Option --</option>
            </select>
            <input type="button" value="Continue" onclick="proceed()">
        </div>
        <input type="hidden" id="csrf" name="${_csrf.parameterName}" value="${_csrf.token}"/>

    </form>

</body>

</html>

1 Ответ

0 голосов
/ 26 марта 2019

CSRF-токен - это токен защиты от подделки, который вам нужно будет передавать обратно в Spring Security при каждом запросе, используя атрибут заголовка Csrf-Token, который вы не включили в вызов ajax, даже если он находится в скрытом поле ввода. Вот почему проверка CSRF завершается неудачно и выдает 403.

Решение предоставлено здесь в этом вопросе SO

Чтобы безбожно скопировать вставить ответ, вот что вам нужно:

$.ajax({
  url: route.url,
  ...
  headers: {
    'Csrf-Token': $('#csrf").val()
  }
});
...