前台请求不带cookie的问题解决方案大汇总
今天碰到一个很棘手的问题,前端请求后端不带cookie,请求时header里面就是没有cookie,可能还少了点其他东西很头疼,尝试了很多办法,还是不行,比如下面几种:1:我是用的axios请求的,很多人只加下面这一行代码就搞定了,但是,我没有// 允许携带cookieaxios.defaults.withCredentials=true2:然后,有人加withCred...
今天碰到一个很棘手的问题,前端请求后端不带cookie,
请求时header里面就是没有cookie,可能还少了点其他东西
很头疼,尝试了很多办法,还是不行,比如下面几种:
1:我是用的axios请求的,很多人只加下面这一行代码就搞定了,但是,我没有
// 允许携带cookie
axios.defaults.withCredentials=true
2:然后,有人加withCredentials之外,还加了其他的一些东西 才成功了,如下:
// 设置
axio.withCredentials = true;
axio.defaults.withCredentials = true;
// 或者这样设置
axio.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
axio.defaults.crossDomain = true;
axio.defaults.withCredentials = true; //设置cross跨域 并设置访问权限 允许跨域携带cookie信息
axio.defaults.headers.common['Authorization'] = ''; // 设置请求头为 Authorization
return axio.post(PATH.FINANCE_APL_LIST,data, {withCredentials:true
}).then(res=>{
console.log("OKOKOK2-------------------",res)
return res.data.retObj
})
但很可惜,我还是失败了
3:有的人说这样加,做一个全局的设置:
import axios from "axios";
// Create an instance using the config defaults provided by the library
// At this point the timeout config value is `0` as is the default for the library
const axio = axios.create({
headers: {
"Content-Type": "application/json;charset=UTF-8"
}
});
// Override timeout default for the library
// Now all requests using this instance will wait 2.5 seconds before timing out
axio.defaults.timeout = 200000;
axio.defaults.withCredentials = true;
原理同一,仍然失败了
4:还有的兄弟说,后端也要配置:
【Access-Control-Allow-Credentials】要为true
【Access-Control-Allow-Origin】设置允许访问的IP不能为【*】,会跟withCredentials=true冲突
于是有了下列的控制:
4-1:只允许自己的前端服务器访问:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class CorsInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
throws Exception {
// 设置允许多个域名请求
String[] allowDomains = {
"http://localhost:3010"
};
Set<String> allowOrigins = new HashSet<String>(Arrays.asList(allowDomains));
String originHeads = httpServletRequest.getHeader("Origin");
if(allowOrigins.contains(originHeads)){
//设置允许跨域的配置
// 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
httpServletResponse.setHeader("Access-Control-Allow-Origin", originHeads);
}
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Headers",
"Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
httpServletResponse.setHeader("X-Powered-By", "Jetty");
String method = httpServletRequest.getMethod();
System.out.println(method);
if (method.equals("OPTIONS")) {
httpServletResponse.setStatus(200);
return false;
}
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}
4-2:允许所有前端服务器访问
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class CorsInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
throws Exception {
String originHeads = httpServletRequest.getHeader("Origin");
httpServletResponse.setHeader("Access-Control-Allow-Origin", originHeads);
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Headers",
"Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
httpServletResponse.setHeader("X-Powered-By", "Jetty");
String method = httpServletRequest.getMethod();
System.out.println(method);
if (method.equals("OPTIONS")) {
httpServletResponse.setStatus(200);
return false;
}
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}
全部都尝试了,然而并没有什么用。
5:最好想啊想,想啊想,会不会是前端工程的问题呢
于是在controller中加了一个测试方法,由于后端需要权限验证
系统未登录前,在浏览器新开一个窗口直接访问,是带cookie的:
登陆后进行在浏览器直接访问,也是带cookie的:
于是有一点眉目了,总结如下:
1:不通过前端工程调用,直接从浏览器访问,非前端工程的ajax/axios等方法调用后端,能携带cookie
2:用本地的前端服务,使用axios等调用后端,不携带cookie
于是,把本地的服务和部署在服务器的服务进行比较:
本地前端服务,访问后端,没有cookie:
惊喜来了,服务器前端服务,访问后端,带Cookie
这就有可能是环境问题了,,,
于是去一番百度谷歌,,,只找到一篇有些类似:
于是只能自己想啊想,想啊想,想起来不带cookie的请求头都有一个【Provisional headers are shown】警告,如下:
又是一顿搜索,下面这个兄弟,说的好啊,虽然没解决我的问题:
想起来我们前端的那个兄弟,好像说过加了一个设置,不缓存请求的资源,每次都去服务器取最新的,会不会是这个问题呢,被设置了开发环境和生产环境的策略不一致?虽然希望渺茫,还是去试了试
关键代码如下:
试了几遍,还是老样子,说明不是这个问题
又找啊找,找啊找,突然想起来,服务器上是用的Docker镜像,前工程用了Nginx做反向代理,应该就是这个原因,又在网上找到两篇文字,发现这两个老哥说的挺对的:
老哥一:
1:最简单粗暴的解决方案
修改项目目录,添加一个XXX的文件夹,把开发环境的需要的静态资源和页面文件放到XXX文件夹下,开发环境下访问项目地址改成http://localhost:8485/XXX。显然这个方案有缺陷,如果cookie path 改变,我们又需要再次改变项目目录结构,可能还需要修改webpack配置(或者其他打包配置)
2:nginx 代理的方式
3:webpack-dev-server 解决方案
关键思路如上:想多了解可看链接:https://segmentfault.com/a/1190000013753896
老哥二:
关键思路如上:想多了解可看链接:https://www.jianshu.com/p/cadab71987d2
所以,,,,今天就到这了,明天加个代理服务试试,应该可以解决问题
后续:果然如此:
package.json中加了一个代理,代理后端地址,解决问题
当然,也可以用Nginx做代理,访问前端和后端
也可以,使用zuul做网关代理,所有工程的访问,先到zuul,再由zuul转发到各自服务,
以上方案都可以,请各位八仙过海,各显神通
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)