set-cookie无法存入到浏览器cookie问题汇总
一、前言最近在做一个前后端分离的自动化平台,由于环境部分还没搭建所以在本地启动前后端服务,开始接口联调,发现一个很有意思的问题,问了三个前端开发也没有解决;最后问题竟然出在一个小细节手中,还是要记录一下前端地址:http://localhost:8080后端地址:http://localhost:9090二、后端基本代码配置后端拦截器部分,不用多说做开发都应该知道public ...
一、前言
最近在做一个前后端分离的自动化平台,由于环境部分还没搭建所以在本地启动前后端服务,开始接口联调,发现一个很有意思的问题,问了三个前端开发也没有解决;最后问题竟然出在一个小细节手中,还是要记录一下
前端地址:http://localhost:8080
后端地址:http://localhost:9090
二、后端基本代码配置
- 后端拦截器部分,不用多说做开发都应该知道
public class CorsInterceptor extends HandlerInterceptorAdapter {
@Value("${service.corsOrigin}") //跨域自定义配置application.yml自己配置
private String corsOrigin;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String origin = request.getHeader("Origin");
//后端响应基本配置项
if (!StringUtils.isEmpty(origin) && corsOrigin.contains(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
response.setHeader("Access-Control-Allow-Methods", "POST, GET");
response.setHeader("Access-Control-Allow-Credentials", "true");
}
//设备默认值
response.setContentType("application/json;charset=UTF-8");
return true;
}
}
1.简要说明setHeader设置的必要性
"Access-Control-Allow-Origin"需要指定前端指定域名,不能用*号,否则无法实现跨域
“Access-Control-Allow-Credentials” 设置成true是告知前端可以请求头携带cookie请求,否则前端将无法进行请求
2.另外前端每次都会发两次请求,其中首次是options请求,该请求为试探性请求可以被拦截器捕获,然后给与前端上述响应的内容,告知对它开放的一些权限及要求
2.拦截器最后要实现WebMvcConfigurer开启拦截器配置,否则上面的代码无法生效,springMVC机制
@Configuration
public class BaseInterceptor implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getCorsInterceptor());
}
@Bean
public CorsInterceptor getCorsInterceptor() {
return new CorsInterceptor();
}
}
3.前端调用后端登录接口,肯定要设置cookie到响应header中,cookie形式本文采用jwt技术
//设置cookie的工具类方法
public static void addCookie(HttpServletResponse response, String name, String value, String domain, int maxAge) {
try {
Cookie cookie = new Cookie(name, URLEncoder.encode(value, "utf-8"));
cookie.setPath("/");
cookie.setDomain(domain);
cookie.setMaxAge(maxAge);
cookie.setHttpOnly(true);
response.addCookie(cookie);
} catch (Exception var6) {
throw new RuntimeException(var6.getMessage());
}
}
图中截图登录接口service层处理cookie的调用方法,在service层设置响应cookie
4.自此后端基本配置完毕,开始前端部分
前端安装 axios、mockjs ,不用多说一个用来进行跨域请求,一个用来开发前的mock数据
5.前端点击登录触发的方法如下
//domain 为后端域名;login为接口
this.$axios.post(baseUrl.domain + baseInterface.login, {
username: this.loginForm.username,
password: this.loginForm.password
})
.then(res => {
if (res.data.code === '20000') {
console.log(res.data.data.token)
//登录成功跳转进入首页
this.$router.push({ path: '/dashboard' })
} else {
var errorInfo = res.data.message
this.openError(errorInfo)
this.loading = false
}
})
} else {
Message.close()
this.loading = false
this.openError()
}
前端的mainjs文件要写入axios全局配置,允许后端写入cookie到浏览器中
axios.defaults.withCredentials = true
6.此时有意思的来了,由于我启动的是开发环境,所以mockjs配置还在只是登录的时候我把,mockjs中的登录mock数据注释掉了,如下
7.然后登录请求后端接口能够成功,并且有真实数据返回,同样后端响应的set-cookie也获取到了
8.理论上后端响应set-cookie后,浏览器能够自动保存cookie到application中,但是很神奇浏览器并没有进行保存
9.然后网上找了很多种说法,说什么前后端不能同域否则不能设置cookie,后端拦截器响"Access-Control-Allow-Origin"不能用*号,“Access-Control-Allow-Credentials” 要设置true这些我都没有问题配置了,然后找了三个前端开发都没有定位到问题
为什么我找前端不找后端,因为后端是没有问题的,我新搭建了一个vue项目然后通过发请求,浏览器能够正常获取到cookie,但是此vue项目就不行,所以后端肯定没问题,就一直在找前端的原因
10.后面有意思的就来了,我控制台突然发现接口请求竟然走的是mockjs
1.当时mockjs登录接口我是注释了的,竟然请求的发出还是走的mock,应该是是被mock拦截了然后由mock转发出去,同样能够请求到后端
2.同样登录cookie无法设置到浏览器后面的接口请求头就无法自动携带cookie请求
11.然后我把mockjs文件全部清空或注释掉,让mockjs无法生效,请求自动变成xhr正常请求,后面的接口也正常
12.或者你在mockjs文件中配置Mock.XHR.prototype.withCredentials = true同样后面的接口也能携带cookie进行请求,但是还是由mock进行转发的
13.所以自此这个问题也就解决了,希望大家不要遇到跟我一样的问题;因为网上没有资料针对我这种情况的,然后下面遇到一个很有趣的问题给大家分享一下
三、有趣的问题发现
1.前后端必须要同等域名下,application才能存入cookie(如果是ng做转发应该就不存在这种必要条件吧)
2.前后端不同域下进行请求,application不能存入cookie,但是不应该后面的接口进行请求
出现这种问题是由于浏览器同源策略导致,也就是说前端是www.baidu.com,请求后端域名也要为www.baidu.com否则application不能存入cookie,浏览器同源策略、浏览器同源策略、浏览器同源策略;重要事情说三遍
前提配置:
前端:http://127.0.0.1:8080
后端:http://localhost:9090
后端要设置前端IP跨域,否则会出现跨域报错
更多推荐
所有评论(0)