Spring security теряет сессию после ajax

182
29 января 2020, 19:10

У меня есть проект на спринг который состоит из двух частей: клиент и сервер. Прошу посморите на гит хаб: клиент: https://github.com/LevOrlov/JM, сервер: https://github.com/LevOrlov/JmServer

На главной странице thumhome у меня есть main.js. В этом скрипте есть ajax.

  • Если ajax незакомментирован, то при любом запросе после входа, происходит потеря сессии и меня перекидывает на страницу с логином.
  • Если ajax закомментирован, то сессия не теряется и я могу переходить по разным страницам

Скажите в чем может быть проблема, в какую сторону смотреть. Спасибо заранее за помощь.

Здесь я приведу код SecurityConfig и файл main.js(где есть ajax запрос).

package com.spring.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@ComponentScan("com.spring")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Qualifier("myUserDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private AuthenticationSuccessHandler successHandler;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/resources/**").permitAll();
        http.authorizeRequests().antMatchers("/static/**").permitAll();
        http.authorizeRequests().antMatchers("/login").permitAll();
        http.authorizeRequests()
                .antMatchers("/admin/**").hasAuthority("ADMIN")
                .antMatchers("/user/**").hasAuthority("ADMIN")
                .anyRequest().authenticated().and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/j_spring_security_check")
                .usernameParameter("username")
                .passwordParameter("password")
                .successHandler(successHandler);
//        http.sessionManagement()
//                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
        http.csrf().disable();
    }
    @Override
    public void configure(WebSecurity security) {
        security.ignoring().antMatchers("/resources/**", "/static/**");
    }
}

main.js

$(document).ready(function () {
        fire_ajax_submit();
});
function display(obj) {
    var id = $(obj).attr('data-id');
    $.ajax({
        type: "GET",
        contentType: "application/json",
        url: "/admin/edit/" + id,
        data: JSON,
        dataType: 'json',
        success: function (data) {
            $("#id1").attr("value", data.id);
            $("#name1").attr("value", data.name);
            $("#login1").attr("value", data.login);
            $("#password").attr("value", data.password);
            $("#modalEdit").css("display", "block");
        },
        error: function (e) {
            var json = "<h4>Ajax Response</h4><pre>"
                + e.responseText + "</pre>";
            $('#feedback').html(json);
            console.log("ERROR : ", e);
        }
    });

}
function fire_ajax_submit() {
//todo передавать в дисплей сразу id
    //todo повесить fire_ajax_submit на onlick в 185 строке thumhome
    $.ajax({
        type: "POST",
        contentType: "application/json",
        url: "/admin/getall",
        data: JSON,
        dataType: 'json',
        success: function (data) {
            var temp = '';
            $.each(data, function (index, value) {
                temp += '<tr>';
                temp += '<td>' + value.id + '</td>';
                temp += '<td>' + value.name + '</td>';
                temp += '<td>' + value.login + '</td>';
                temp += '<td>' + '<button onclick="display(this)"' + ' class="btn btn-info show-modal editbutton"' + 'data-id=' + value.id + ' >Edit</button>' + '  ' + '<a class="btn btn-danger" href="/admin/delete/' + value.id + '"' + '  type="button">Delete</a>' + '</td>';
                temp += '</tr>';
            })
            $('#tablejs').append(temp);
        },
        error: function (e) {
            var json = "<h4>Ajax Response</h4><pre>"
                + e.responseText + "</pre>";
            $('#feedback').html(json);
            console.log("ERROR : ", e);
            $("#btn-search").prop("disabled", false);
        }
    });
}
Answer 1

Если я правильно понимаю, что клиент и сервер - это разные приложения и разворачиваются, соответственно, на разных портах, то проблема, скорее всего заключается в [CORS][1]. jQuery по умолчанию не передаёт в AJAX-запросе сессионную куку, если запрос выполняется на origin (адрес+порт), отличный от origin'а текущей страницы. Spring Security, получив запрос без сессионной куки, просто создаёт новую сессию и куку, из-за чего аутентификация "пропадает".

Возможные решения данной проблемы:

  • Размещать клиент и сервер на одном origin (единым приложением или при помощи механизма обратного проксирования в Apache HTTPD или nginx, например)

  • Или настроить CORS в Spring Security и заставить jQuery передавать куку в запросе:

$.ajax({ 
    url: a_cross_domain_url, 
    xhrFields: { 
        withCredentials: true 
    } 
});

READ ALSO
java.lang.reflect.InvocationTargetException как исправить?

java.lang.reflect.InvocationTargetException как исправить?

Только начал разбираться в javafx и сразу же столкнулся с проблемой,просто перенес проект из java и добавил listview, только вот все пошло не по плануКак...

167
разделитель числа

разделитель числа

какой нужно использовать плагин в java чтобы выводилось число по разряду(например: 1234567 нужно чтоб выводилось 1 234 567)

155
Как отследить любое обращение к JCR ноде?

Как отследить любое обращение к JCR ноде?

Начинаю работать с AEM (Adobe Experience Manager - он же CQ)

139