【SpringSecurity】SpringSecurity+Vue前后端分离使用验证码时后端存入到session中是null值的问题解决
前后端分离跨域问题、session问题
1. 问题描述
SpringSecurity+Vue前后端分离使用验证码,后端将生成的验证码存入到session中,但是在进行验证码验证时获取session中的验证码值时null的,后端生成的验证码确实是生成好了。问题就是存不进session中。
2. 解决问题:以下三种方式
- 后端设置跨域:后端跨域问题有很多解决方式,这里只写一种通过配置类的方式。
- 主要跨域类
/**
* 解决跨域请求的
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 你需要跨域的地址 注意这里的 127.0.0.1 != localhost
// * 表示对所有的地址都可以访问
// corsConfiguration.addAllowedOrigin("http://127.0.0.1");
corsConfiguration.addAllowedOrigin("http://localhost");// 填自己的域名
// 跨域的请求头
corsConfiguration.addAllowedHeader("*"); // 2
// 跨域的请求方法
corsConfiguration.addAllowedMethod("*"); // 3
//加上了这一句,大致意思是可以携带 cookie
//最终的结果是可以 在跨域请求的时候获取同一个 session
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//配置 可以访问的地址
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
}
实在不行的可以把跨域的方法全部加入跨域类、即如下
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 解决跨域请求的
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
// 方式一、返回CorsConfiguration 对象
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 你需要跨域的地址 注意这里的 127.0.0.1 != localhost
// * 表示对所有的地址都可以访问
// corsConfiguration.addAllowedOrigin("http://127.0.0.1:8080");
// corsConfiguration.addAllowedOrigin("http://localhost:8090/");
// corsConfiguration.addAllowedOrigin("http://yuechi.com");
corsConfiguration.addAllowedOrigin("*");
// 跨域的请求头
corsConfiguration.addAllowedHeader("*"); // 2
// 跨域的请求方法
corsConfiguration.addAllowedMethod("*"); // 3
//加上了这一句,大致意思是可以携带 cookie
//最终的结果是可以 在跨域请求的时候获取同一个 session
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
// 方式二、加入bean
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//配置 可以访问的地址
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
/* 方式三、覆盖 WebMvcConfigurer 里的*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
注意:在设置了allowCredentials(true)之后,allowedOrigins()就不能再设置为allowedOrigins("*"),而是把 * 替换成自己的域名,因为*不允许携带认证头和cookies,如果是*的话,浏览器将不会发送cookies,即使你的XHR设置了withCredentials。如果项目不需要session那么可以直接设置为 * 。这里我之前就是设置成*而我项目有需要session存放生成的验证码,所以经过自己设置的验证码过滤器时在session中没有拿到对应值(session是空的)。
相关原理:如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的也无法读取服务器域名下的Cookie。
删除线格式
参考链接:
- 前端设置跨域:
- 通过新建
vue.config.js文件添加,文件内容如下
module.exports = {
// 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath
// baseUrl: process.env.NODE_ENV === 'production' ? './' : '/'
publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './',
// 输出文件目录:在npm run build时,生成文件的目录名称
outputDir: 'dist',
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
assetsDir: "assets",
// 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度
productionSourceMap: false,
// 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变)
filenameHashing: false,
// 代码保存时进行eslint检测
lintOnSave: false,
// webpack-dev-server 相关配置
devServer: {
// 自动打开浏览器
open: true,
host: 'localhost',
// 端口
port: 8090,
// https
https: false,
// 热更新
hotOnly: false,
// 使用代理
proxy: {
'/api': {
// 目标代理服务器地址
target: 'http://localhost/',
// 开启代理,本地创建一个虚拟服务器 允许跨域
changeOrigin: true,
},
},
},
}
- 通过axios添加前缀,在
main.js中添加以下代码(前端常用方式,但是我出现的这个问题单单加这个解决不了)
// axios前缀,写了前缀发送axios请求时就可以不用在写前缀了,直接写接口地址
axios.defaults.baseURL = "http://localhost:8090/";
- 通过在
main.js添加axios.defaults.withCredentials = true;的方式,让当前请求为跨域类型时是在请求中协带cookie(也就是上面黄字的原理)。
// axios前缀也要加,
axios.defaults.baseURL = "http://localhost:8090/";
axios.defaults.withCredentials = true;
通过xhr设置,在axios请求头中添加。
相关原理:withCredentials:表示XHR是否接收cookies和发送cookies,也就是说如果该值是false,响应头的Set-Cookie,浏览器也不会理,并且即使有目标站点的cookies,浏览器也不会发送。因为在默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。如果服务器接收带凭据的请求,会用下面的HTTP头部来响应。
虽然设置了widthCredentials为true的请求中会包含远程域的所有cookie,但这些cookie仍然遵循同源策略,所以外域是访问不了这些cookie的,现在我们就可以安全地跨域访问啦。
需要注意是,当配置了xhr.withCredentials = true时,必须在后端增加 response 头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。
如果在同域下配置xhr.withCredentials,无论配置true还是false,效果都会相同,且会一直提供凭据信息(cookie、HTTP认证及客户端SSL证明等)
- 通过
cors插件,在main.js中添加。
const cors = require('koa2-cors');
app.use(cors({
origin: "http://localhost:8090",// 即http://域名:端口
credentials: true,
}));
3. 总结
- 前后端分离的项目,后端设置跨域的方式有多种,前端的解决方式也有几种
- 需要特别注意如果要发送
Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名、当配置了xhr.withCredentials = true时,必须在后端增加 response 头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为* - 需要发送Cookie时就需要注意前后端跨域的匹配设置
- 如果还是不能解决,就前后端各种搭配设置分离,肯定有一种可以
更多推荐
所有评论(0)