今天碰到一个很棘手的问题,前端请求后端不带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转发到各自服务,

 

以上方案都可以,请各位八仙过海,各显神通

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐