Проблемы со входом в Spring Security AJAX/JSON

Я пытаюсь реализовать Spring Security с формой входа в систему, отправляемой через Ajax. Я создал свой собственный аутентификационныйFailureHandler и свой собственный аутентификационныйSuccessHandler. Я не уверен, что моя проблема заключается в моем коде Spring/Java или в моем коде на стороне клиента. Я также видел, что проблема может быть связана с защитой от межсайтовых сценариев. Когда я вхожу в систему, он проходит проверку подлинности, но на самом деле я получаю новую HTML-страницу с моим JSON, но тип содержимого — html/text.

введите здесь описание изображения

Когда вход не удался, я получаю то же самое.

введите здесь описание изображения

Заголовки запроса и ответа мне не кажутся правильными. Во-первых, нет заголовков ответов, а во-вторых, в заголовках запросов нет X-Requested-With.

Некоторые пункты на заметку

  1. Я использую Spring Boot 1.2.5
  2. У меня включен CSRF в Spring Security, это требование клиента
  3. Не может быть страницы входа, логин должен быть в правом верхнем углу верхней навигации/заголовка, поэтому я отправляю через JS/Ajax

Вот как будет выглядеть форма входа:

введите здесь описание изображения

Вот мои пользовательские обработчики

@Component
public class AuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Autowired
    private UserMapper userMapper;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {

        userMapper.incrementFailedLogin(request.getParameter("sec-user"));

        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().print("{\"success\": false}");
        response.getWriter().flush();
    }
}

-

@Component
public class AuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    @Autowired
    private UserMapper userMapper;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws ServletException, IOException {

        userMapper.updateUserOnAuthSuccess(request.getParameter("sec-user"));

        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().print("{\"success\": true}");
        response.getWriter().flush();
    }
}

Моя конфигурация безопасности Spring

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    AuthFailureHandler authFailureHandler;

    @Autowired
    AuthSuccessHandler authSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/", "/about","/public/**").permitAll()
                    .anyRequest().fullyAuthenticated()
                    .and()
                .formLogin()
                    .usernameParameter("sec-user")
                    .passwordParameter("sec-password")
                    .failureHandler(authFailureHandler)
                    .successHandler(authSuccessHandler)
                    .permitAll()
                    .and()
                .logout()
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/")
                    .deleteCookies("remember-me", "JSESSIONID")
                    .permitAll()
                    .and()
                .rememberMe();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }
}

Форма входа (Thymeleaf) — встроена в меню навигации

<div th:fragment="login">
        <form th:action="@{/login}" method="post" accept-charset="UTF-8" class="login-pane" id="login-form">
            <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
            <div class="form-group">
                <label for="sec-user">Email</label>
                <input type="email" class="form-control" id="sec-user" name="sec-user" placeholder="Email" />
            </div>
            <div class="form-group">
                <label for="sec-password">Password</label>
                <input type="password" class="form-control" id="sec-password" name="sec-password" placeholder="Password" />
            </div>
            <button type="login-btn" class="btn btn-danger">Login</button>
        </form>
    </div>

И последнее, но не менее важное: мой javascript-код.

$(document).ready(function() {

    $("#login-btn").click(login)

});

function login() {

    console.info("Attempting to authenticate");

    $.ajax({
        type: 'POST',
        url: '/login',
        data: $('#login-form').serialize(),
        cache: false,
        dataType: "json",
        crossDomain: false,
        success: function (data) {
            var response = jQuery.parseJSON(data);
            if (response.success == true) {
                console.info("Authentication Success!");
                window.location.href("/");
            }
            else {
                console.error("Unable to login");
            }
        },
        error: function (data) {
            console.error("Login failure");
        }
    });
}

person greyfox    schedule 31.07.2015    source источник


Ответы (1)


Вы не вызываете метод login(), определенный в javascript, а фактически отправляете действие login в форме входа.

Удалите вызов действия post и вызовите метод login() для события onclick кнопки входа.

person Himanshu    schedule 01.08.2015
comment
Проблема заключалась в том, что у меня было ‹button type=login-btn class=btn btn-danger›Войти‹/кнопка› вместо ‹button id=login-btw type=button class=btn btn-danger›Login‹/button› - person greyfox; 03.08.2015