使用Cookie解决单点登录

目的
登录信息共享三个网站(即单点登录)
aaa.chen.com 、bbb.chen.com 、ccc.chen.com
实现自动登录
技术点
1、设置Cookie的路径为setPath("/") .即Tomcat的目录下都有效
2、设置Cookie的域setDomain("chen.com");即aaa.chen.com 、bbb.chen.com 、ccc.chen.com有效。即跨域。
3、设置Cookie的时间。即使用户不选择在几天内自动登录,也应该保存Cookie以保存在当前浏览器没有关闭的情况下有效。
4、使用Filter自动登录。
5、模拟数据库存储加密密码
6、巧妙加解密cookie,防止别人修改过期时间等
实现
结构图

在这里插入图片描述

index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>CCC站点</title>
</head>
<body>
	<p>
		在同一台服务器上,多个站点自动登录....>>:<%=session.getId()%></p>
	<c:if test="${empty sessionScope.username}">
		<form name="f" method="post" action="<c:url value='/login'/>">
			Name:<input type="text" name="username" /><br /> Pwd:<input type="text"
				name="password" /><br /> <input type="checkbox" name="chk" value="7">一周内自动登录<br />
			<input type="submit" value="登录" />
		</form>
	</c:if>
	<c:if test="${not empty sessionScope.username}">
    		欢迎你:${user}。<a href="<c:url value='/loginout'/>">安全退出</a>
	</c:if>
	<br /> 相关站点:(只要在一边登录成功,即可以自动登录到另一个程序)
	<br />
	<a href="http://aaa.chen.com">aaa.chen.com</a>
	<br />
	<a href="http://bbb.chen.com">bbb.chen.com</a>
	<br />
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>SSObyCookie</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>

	<filter>
		<filter-name>AutoLoginFilter</filter-name>
		<filter-class>com.chen.filter.AutoLoginFilter</filter-class>

	</filter>
	<filter-mapping>
		<filter-name>AutoLoginFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

AutoLoginFilter.java
package com.chen.filter;

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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.chen.util.Util;


public class AutoLoginFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletRequest req=(HttpServletRequest)request;
		HttpServletResponse resp=(HttpServletResponse)response;
		
		String username = (String) req.getSession().getAttribute("username");
		
		if(username==null){
			Cookie[] cookies = req.getCookies();
			if(cookies!=null){
				for (Cookie cookie : cookies) {
					String name = cookie.getName();
					if(name.equals("autologin")){
						String encodeCookie = cookie.getValue();
						if(Util.loginByCookie(encodeCookie)){//cookie是否有效
							req.getSession().setAttribute("username", name);
						}
					}
				}
			}
		}
		chain.doFilter(req, resp);
	}

	@Override
	public void destroy() {
		
	}

}

LoginServlet.java
package com.chen.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chen.db.MyDB;
import com.chen.util.Util;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		String forward="/index.jsp";
		
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		String chk = req.getParameter("chk");
		System.out.println("chk:"+chk);
		
		if(username!=null&&!username.trim().equals("")&&password!=null&&!password.trim().equals("")){
			//先加密密码
			String MD5password = Util.EncodePassword(password);
					
			//模拟从数据库中获取加密密码
			String pwd = MyDB.getInstance().getMap().get(username);
			
			if(MD5password.equals(pwd)){
				req.getSession().setAttribute("username", username);
				int time = 1*60*60*24*7;//7天
				long timeLong=System.currentTimeMillis()+time;
				String encodeCookie = Util.EncodeCookie(username, MD5password, String.valueOf(timeLong));
				//即使没有选择自动登录,也要在浏览器关闭前这段时间使用cookie
				Cookie cookie = Util.setCookie(encodeCookie, null);
				if(chk!=null){
					cookie.setMaxAge(time);//选择了自动登录
					resp.addCookie(cookie);
				}
			}
		}
		
		//这里因为登陆页和成功登陆是同一个页面,所以没有改变forward的值
		req.getRequestDispatcher(forward).forward(req, resp);
	}

}
MyDB.java
package com.chen.db;

import java.util.HashMap;
import java.util.Map;

public class MyDB {
	
	private static MyDB mydb;
	private Map<String,String> map=new HashMap<>();
	
	{
		map.put("zhangsang", "117ec018fe460940b50ceb6fa053e879");//123
		map.put("xiaoli", "01d7d30a3c7b731636c076e3fb12fd9c");//456
	}
	
	private MyDB(){}
	
	public static MyDB getInstance(){
		if(mydb==null){
			mydb=new MyDB();
		}
		return mydb;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

}

Util.java
package com.chen.util;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.tomcat.util.codec.binary.Base64;

import com.chen.db.MyDB;

import sun.misc.BASE64Encoder;

public class Util {

	private static String key = "4836";

	// 加密的cookie信息
	public static String EncodeCookie(String username, String MD5Password, String expiryTime) {
		String str = username + ":" + expiryTime + ":" + MD5Password + ":" + Util.key;
		String signatureValue = DigestUtils.md5Hex(str.getBytes());

		String tokenValue = username + ":" + expiryTime + ":" + signatureValue;
		String cookie = new String(Base64.encodeBase64(tokenValue.getBytes()));

		return cookie;
	}

	// 加密的密码
	public static String EncodePassword(String password) {
		String str = password + Util.key;
		String MD5Password = DigestUtils.md5Hex(str.getBytes());
		return MD5Password;
	}

	// 解密cookie
	public static Map DecodeCookie(String encodeCookie) {
		Map<String, String> map = null;

		byte[] bytes = Base64.decodeBase64(encodeCookie);
		String decodeCookie = new String(bytes);
		String[] split = decodeCookie.split(":");
		if (split != null && split.length == 3) {
			map = new HashMap<>();
			map.put("username", split[0]);
			map.put("expiryTime", split[1]);
			map.put("signatureValue", split[2]);
		}
		return map;
	}

	// cookie是否有效
	public static boolean loginByCookie(String encodeCookie) {
		if (encodeCookie != null && !"".equals(encodeCookie)) {
			Map map = DecodeCookie(encodeCookie);
			if (map != null) {
				String username = (String) map.get("username");
				String expiryTime = (String) map.get("expiryTime");     
				String signatureValue = (String) map.get("signatureValue");

				long time = Long.valueOf(expiryTime);
				long currentTimeMillis = System.currentTimeMillis();

				if (time > currentTimeMillis) {   //解密cookie中带上expiryTime是为了防止别人修改cookie的时间
					String str = username + ":" + expiryTime + ":" + MyDB.getInstance().getMap().get(username) + ":"
							+ Util.key;
					String signatureValueCurrent = DigestUtils.md5Hex(str.getBytes());
					if (signatureValue.equals(signatureValueCurrent)) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	public static Cookie setCookie(String encodeCookie,Integer time){
		Cookie cookie = new Cookie("autologin", encodeCookie);
		cookie.setPath("/");
		cookie.setDomain("chen.com");
		if(time!=null){
			cookie.setMaxAge(time);  //这个是为了让浏览器决定带不带cookie,不安全,可以被人修改,所以在解密cookie中还带了expiryTime
		}
		return cookie;
	}

}

Logout.java
package com.chen.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.chen.util.Util;

@WebServlet("/loginout")
public class Logout extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
			HttpSession session = req.getSession();
			
			//这里存在一个问题
			//同一浏览器访问同一台服务器上的不同站点用的是不同的session
			//这里只移除了某一个网站的session属性
			//其他的网站的session属性还保留着,只要浏览器没有关闭,照样可以访问资源
			session.removeAttribute("username"); 
			
			Cookie cookie = Util.setCookie("", 0);
			resp.addCookie(cookie);
			
			resp.sendRedirect(req.getContextPath()+"/index.jsp");
	}

}

部署参考:同一台Tomcat的多域名绑定

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值