如何让同一服务,ip域名session共享。

这几天碰到一个问题,一个统一登录服务配置了域名,但是要求用户不管通过域名访问还是ip访问,保证都能登录成功。

服务本身就是负载的,一个nginx下面配置了多个一样的服务,所以第一步应该保证这些分布式应用session是共享的,我们采用了分布式共享session,也就是redis+cookie。所有服务连接同一redis集群,实现session共享,服务端生成cookie到浏览器。

因为cookie生成的限制,domain只能是用户访问本身所输入的地址,例如用户输入http://lcaolhost:8080那么服务生成的cookie的domain为localhost,如果输入http://127.0.0.1:8080那么服务生成的cookie的domain为127.0.0.1,所以就造成了生成的cookie不一样,同事cookie里面存放的sessionId也不一样,浏览器会认为你是访问了两个服务,就造成了域名和ip访问不一致。

为了解决这个问题,我就想着在用户登录成功后同时给他生成另一个cookie不就行了,里面存放一样的sessionId,于是就有了下面的代码。

	String sessionId = request.getParameter("sessionId");
	Cookie cookie = new Cookie("SSO-SID", sessionId);
        cookie.setDomain("127.0.0.1"); 
	cookie.setPath("/");
	response.addCookie(cookie);  //将cookie返回到客户端
	request.getRequestDispatcher("/index.html").forward(request,response);

大体意思是当用户访问localhost:8080/xxxx登录成功后生成额外生成一个127.0.0.1的cookie,结果肯定是失败了。因为浏览器认为你生成了其他网站的cookie,自然是不行。

所以我就想着转发一下,绕一下,让服务自己生成自己的,于是有了下面的代码。

在访问http://localhost:8080/login登录页面时,将sessionId获取返回到页面。


	String JSESSIONID = request.getSession().getId();

	model.addAttribute("sessionId",JSESSIONID);


登录页面引入一段js来接收这个sessonId,顺便访问一下自己的ip的某个接口。



接口里面生成127.0.0.1的cookie。


	@RequestMapping(path="/cologin",method=RequestMethod.GET)
	public void revokeToken(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String sessionId = request.getParameter("sessionId"); 
		Cookie cookie = new Cookie("SSO-SID", sessionId);
//			cookie.setDomain(""); //这里可以不同填写,默认就是访问地址
		cookie.setPath("/");
		response.addCookie(cookie);  //将cookie返回到客户端
		request.getRequestDispatcher("/index.html").forward(request,response);

	}


这样浏览器里面就产生了两个cookie,存放的sessionId是一样的,domain分别为localhost和127.0.0.1。变向解决了这个问题。


其实,这种方法也可以用作多个不同域名的情形,或者多个不同的服务域名也不相同的情形。而且这里可以做一下安全校验,就是传输sessionId的时候不用明文传送,可以用作一个随机字符串或者主键,将这个字符串和redis或者数据库里面的session绑定即可。


你可能感兴趣的:(java)