2019独角兽企业重金招聘Python工程师标准>>>
在做web项目时,遇到前后端分离的项目,第一个要解决的就是跨域问题,然后就是保存用户信息的session和cookie的问题,通常使用二者的结合使用。然而在实际的开发中,对于前后端分离的项目,每次ajax请求无法携带cookie到后端,导致每次都会新创建一个session,而无法获取login时保存的信息。
先来说一下代码的解决方法:(这里是maven项目,使用的是spring mvc)
一、后端;
后端自定义实现了servlet 的filter,也就是 解决跨域问题的通用方法之一Cross;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletResponse resp = (HttpServletResponse) response;
HttpServletRequest rep = (HttpServletRequest) request;
resp.addHeader("Access-Control-Allow-Origin", rep.getHeader("Origin"));
//允许跨域请求中携带cookie
resp.addHeader("Access-Control-Allow-Credentials", "true");
// 如果存在自定义的header参数,需要在此处添加,逗号分隔
resp.addHeader("Access-Control-Allow-Headers", "authorization,Origin, No-Cache, X-Requested-With, "
+ "If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, " + "Content-Type, X-E4M-With");
resp.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
chain.doFilter(request, response);
}
二、前端:
ajax请求添加以下参数:
crossDomain: true, xhrFields: { withCredentials: true },
整体ajax为:
$.ajax({
url : patl,
type: "POST",
crossDomain: true,
xhrFields: {
withCredentials: true
},
success : function(result) {
alert("success");
}
});
下面描述一下上面的代码;
首先ajax 添加 withCredentials: true ,这是指定这个请求应该发送凭据。
而 crossDomain: true, 则是解决跨域配置。
对应的后端配置,要在filter 的 header 中添加 Access-Control-Allow-Credentials 为true,这是允许跨域请求携带cookie,
这是还需要设置Access-Control-Allow-Origin ,若 这个设置为“*”,则 当请求发出时,浏览器就报错如下 : Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'null' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
这是因为这样设置和前端跨域请求携带cookie产生了冲突,这时把“*” 换作前端项目的部署服务器的ip即可。
这样更改若后端项目只和web端有交互还好(并且前后端不分离,分离的话前端ip是变化的),若又和app或是别的有交互的话,就会出现问题,请求无法携带凭证。
因为在做项目时刚好后端既要和web端有交互,又与app端有交互,so,以上方法无法解决。
查阅资料有的说把“*”换作null 就可以了,但 在我这 也不好使,
最后通过查阅资料并和同事探讨,把“*” 换成rep.getHeader("Origin"),这样每次请求获取请求的Origin,无论前端怎么变化,但在同一个浏览器窗口中ip是不变的,所以这样相当于动态设置Origin,完美解决问题。
通过上述的配置,针对前后端分离的项目,每次ajax 请求可以携带cookie了,这样在同一个浏览器窗口中每次请求到后端的session就变成了一个,这样就可以做一些token验证之类的操作了(若每次请求不是一个session,则需要查看登录时 前端是否自动写入了cookie,若没有写入,则需要手动将sessionId写入到cookie中,key=“JSESSIONID” ,vlue为第一次登录请求返回来的sessionId)。