最近在写一个demo,是前后端分离的,前端通过使用axios来发送异步请求来获取后端的数据,后端使用了SpringSecurity来做系统的鉴权,但发现,SpringSecurity总是拿不到session的问题。
前言:
由于SpringSecurity中,很多东西都是基于session来做的,比如,当用户登录成功后,会创建一个SecurityContextHolder,里面存储了用户认证后的token数据,然后将其存储到session中。
当该用户的后续请求再过来时,如用户的权限鉴定,会先到session中把该 SecurityContextHolder取出来,这样就不需要重复的到数据库中查询用户的数据。
问题:
axios在发送异步请求是,无法携带sessionid,导致后端在处理请求时,会为其创建新的的会话,所以在用户登录成功后,在下一次请求,(访问带权限的url)做用户鉴权时就无法获取到用户的认证信息,这样SpringSecurity就会提示用户未登录,访问无权限的限定的url是,会看到用户的角色是“匿名的”。
解决:
想要解决这个问题也很简单,思路就是然axios每次发送请求时,都带上session_id,这样后端就可以识别出这是哪个session。
axios的设置:
将withCredentials设置为true,默认为false。意思是允许请求时携带cookic信息。
因为http是无状态的,所以session信息会存放在cookic中,随请求携带。
import axios from 'axios'
axios.defaults.baseURL="http://localhost:8081"
//让请求携带cookic信息
axios.defaults.withCredentials=true
CORS跨域设置
这里主要注意两个点:
1.Origin不能使用通配符 " * "
2.Credentials要设置为true
这里以SpringSecurity配置CORS为例
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(new SmsLoginEntryPoint())
.and()
.authorizeRequests()
.antMatchers("/app/**").permitAll()
.antMatchers("/user/**").hasRole("user")
.antMatchers("/admin/**").hasRole("admin")
.and()
.formLogin().permitAll()
.and()
.cors()
.configurationSource(configurationSource()) //配置SpringSecurity的跨域问题
.and()
.csrf().disable()
.apply(smsAuthenticationSecurityConfig)
.and().addFilterBefore(new SuccessFilter(), UsernamePasswordAuthenticationFilter.class);
// .and()
// .addFilterAfter(new UserAccessSecurityFilter(), FilterSecurityInterceptor.class);
}
//配置跨域请求
CorsConfigurationSource configurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedHeader("*");//设置被允许的请求头字段,*表示允许所有字段
corsConfiguration.addAllowedMethod("*");//设置允许的请求方法,*表示允许所有请求方法
corsConfiguration.addAllowedOrigin("http://localhost:8080");//设置允许的域,*表示允许所有的域
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setMaxAge(3600L);//设置预检请求有效期,有效期内不必再次发送预检请求,默认是1800秒
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);
return source;
}