登录信息共享三个网站(即单点登录)
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,防止别人修改过期时间等
<%@ 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()%>
欢迎你:${user}。安全退出
相关站点:(只要在一边登录成功,即可以自动登录到另一个程序)
aaa.chen.com
bbb.chen.com
SSObyCookie
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
AutoLoginFilter
com.chen.filter.AutoLoginFilter
AutoLoginFilter
/*
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() {
}
}
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);
}
}
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;
}
}
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;
}
}
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的多域名绑定