最近由于公司的项目需求,需要跟甲方对接,对方使用的是spring session框架实现的session共享,调试了整整一周才基本流程跑通,期间遇到了不少的坑,接下来就把遇到的坑总结下来,方便以后进行查看,也可以给大家准备使用spring session共享提供个参照,初次写博客,请多关照,闲话少说,接下来谈谈遇到的坑
1:第一个坑就是我们项目采取的前后端分离的技术架构和部署模式,这样就不可避免的跨域了,这样跨域之后就引发了很多问题,最重要的问题就是,前端即使是同一个html中每发送一个ajax请求都是一个独立的session,sessionID不一样,这样就不能实现session共享,解决方案前后端需同时配合开启Access-Control-Allow-Credentials 具体代码如下:
第一 后端使用cors解决跨域,并将Access-Control-Allow-Credentials 设置为true,由于我使用的spring boot框架,跨域过滤器代码如下:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
/**
*
* @ClassName: CorsFilter
* @Description: 跨域过滤器设置header跨域,并将跨域接受cookie开启
* @author * @date 2017年3月7日
*
*/
@Component
public class CorsFilter implements Filter {
private Logger logger = Logger.getLogger(CorsFilter.class);
private final String prefix = "===================";
@Override
public void destroy() {
logger.info(prefix+"CorsFilter过滤器销毁");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse) res;
// 切记当Access-Control-Allow-Credential设置为true的时候,Access-Control-Allow-Origin 不能用*,可以用前端的域名或者像我这样写,这个坑调试了好久。。
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
//是否支持cookie跨域
response.setHeader("Access-Control-Allow-Credentials","true");
logger.info(prefix+"设置跨域heade结束");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config) throws ServletException {
logger.info(prefix+"CorsFilter过滤器初始化");
}
}
第二:后端已经开启接收cookie凭据验证,则前端在发送ajax请求的时候需要将Access-Control-Allow-Credentials 设置为true,具体代码如下,由于使用的html5的特性,会导致有些浏览器不支持,IE10及以下不支持html5,代码如下
$.ajax({ type: 'post', url: "localhost:8080/three/pro/saveTest", xhrFields: { withCredentials: true }, crossDomain: true, data: JSON.stringify(param), success: function(data) { message = data.result; if (message == false) { alert("保存失败"); } }, error: function() {} });
注意主要就是这个属性这样前端就开启了cookie发送,这样前端页面中的session就相同了:
xhrFields: { withCredentials: true }, crossDomain: true,
经过以上两个步骤,跨域的问题是解决了,sessionID也相同了,接下来聊聊我遇到的第二个坑
2:第二坑也是坑的我好惨,由于我们项目是调用的第三方的登录html,比如说,我们的域名是test.ceshi.com 而第三方的域名是testbuilder.ceshi.com 这样进行调试发现这两个域名的session始终不能共享,通过火狐浏览器查看cookie发现,他们两个域名没有公用一个cookie,一个test.ceshi.com的cookie,一个是testbuilder.ceshi,com 的cookie,看到这样我就去查看spring session 的源码,发现spring session 默认使用cookie 保存和传递 sessionId,具体详细情况请参考
http://blog.csdn.net/alaska_bibi/article/details/53126456?locationNum=3&fps=1
除了根据以上博客修改getCookiePath为获取根目录,另外还需要在writeCookieValue 中设置domainName 为ceshi.com 注意 前面没有“.”这样一来他们的cookie就都在ceshi.com的根路径下,这样就实现了session跨域共享,初次写博客可能描述不是很清楚,请多多包涵