使用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,防止别人修改过期时间等
实现
结构图

使用Cookie解决单点登录_第1张图片

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"%>




CCC站点


	

在同一台服务器上,多个站点自动登录....>>:<%=session.getId()%>

Name:
Pwd:
一周内自动登录
欢迎你:${user}。安全退出
相关站点:(只要在一边登录成功,即可以自动登录到另一个程序)
aaa.chen.com
bbb.chen.com
web.xml


	SSObyCookie
	
		index.html
		index.htm
		index.jsp
		default.html
		default.htm
		default.jsp
	

	
		AutoLoginFilter
		com.chen.filter.AutoLoginFilter

	
	
		AutoLoginFilter
		/*
	



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 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 getMap() {
		return map;
	}

	public void setMap(Map 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 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的多域名绑定

你可能感兴趣的:(JavaWeb)