最近公司要做一個單點登陸的應(yīng)用,整合論壇和網(wǎng)站。到網(wǎng)上找了好些資料,終于圓滿解決,博客中記錄一下一面忘掉。
單點登錄首先首先要保持?jǐn)?shù)據(jù)庫數(shù)據(jù)的一致性,這個實現(xiàn)方式很多我就不多廢話了。
剛開始我的想法是在一個應(yīng)用中登陸的時候發(fā)送一個http請求到另一個應(yīng)用保證兩個應(yīng)用同時擁有session,后來考慮到session過期不同步的問題只能放棄。為了保持session的完全同步我只能求助于cookie,首先說一下思路:
1.為了兩個應(yīng)用個應(yīng)用能同時訪問到cookie,cookie設(shè)置的時候要設(shè)置path在根目錄(同一個服務(wù)器下的不
同應(yīng)用,不在同一個應(yīng)用下可以用共用域名比如說 .baidu.com),必須保證cookie在統(tǒng)一一個域下
2.在訪問一個應(yīng)用的時候首先檢測session如果存在就是已經(jīng)登錄保存cookie(保證cookie是最新的)
3.如果session不存在檢測cookie如果cooki不存在說明在另一應(yīng)用中也沒有登錄
4.cookie存在檢測創(chuàng)建時間(當(dāng)然保存的時候要設(shè)置一個時間)如果沒有過期就用cookie中保存的用戶名密碼調(diào)用一下登錄方法
5.登陸成功保存cookie
為了保證每次請求都能檢測我使用了filter下面貼一下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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginFilter implements Filter {
private String loginInfoPath;
public void destroy() {
loginInfoPath = null;
}
public void doFilter(ServletRequest sreq, ServletResponse sresp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse resp = (HttpServletResponse) sresp;
Class loginInfoClass = null;
LoginInfoBase loginInfo = null;
try {
loginInfoClass = Class.forName(loginInfoPath);
loginInfo = (LoginInfoBase) loginInfoClass.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
loginInfo.setReq(req);
loginInfo.setResp(resp);
//session值為空
if(loginInfo.isSessionEmpty()){
if(loginInfo.init()){
boolean loginResult = loginInfo.doLogin();
if(loginResult){
loginInfo.saveCookie();
}
}
}else{
if(loginInfo.init()){
//另外一套系統(tǒng)已經(jīng)退出
if("out".equals(loginInfo.getLoginState())){
loginInfo.doLogout();
CookieUtil.delCookie(resp, LoginInfoBase.COOKIE_NAME);
}
}
}
chain.doFilter(sreq, sresp);
}
public void init(FilterConfig config) throws ServletException {
this.loginInfoPath = config.getInitParameter("loginInfoPath");
}
public String getLoginInfoPath() {
return loginInfoPath;
}
public void setLoginInfoPath(String loginInfoPath) {
this.loginInfoPath = loginInfoPath;
}
}
loginInfoPath 在web.xml中配置指明LoginInfoBase的子類的完整路徑用來反射
LoginInfoBase代碼:
package com.yt.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class LoginInfoBase {
public static final String SEPARATION = "-->";
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final long COOKIE_TIME = 1800000;
public static final String COOKIE_NAME = "loginInfo";
public static final String COOKIE_PATH = "/";
protected HttpServletRequest req;
protected HttpServletResponse resp;
protected Date sessionTime;
protected String userName;
protected String userPass;
protected String loginState;
public LoginInfoBase() {
super();
}
public LoginInfoBase(HttpServletRequest req, HttpServletResponse resp) {
super();
this.req = req;
this.resp = resp;
}
public LoginInfoBase(String userName, String pwd, Date sessionTime) {
this.userName = userName;
this.userPass = pwd;
this.sessionTime = sessionTime;
}
abstract void doLogout();
abstract boolean isSessionEmpty();
abstract boolean doLogin();
public HttpServletRequest getReq() {
return req;
}
public void setReq(HttpServletRequest req) {
this.req = req;
}
public HttpServletResponse getResp() {
return resp;
}
public void setResp(HttpServletResponse resp) {
this.resp = resp;
}
//初始化登錄對象
protected boolean init(){
String loginInfoStr = CookieUtil.getValue(req, LoginInfoBase.COOKIE_NAME);
if(loginInfoStr == null || "".equals(loginInfoStr)){
return false;
}
String[] infoArray = loginInfoStr.split(SEPARATION);
if(infoArray.length>3){
this.userName = DigestUtil.getFromBASE64(infoArray[0]);
this.userPass = DigestUtil.getFromBASE64(infoArray[1]);
this.sessionTime = buildDate(infoArray[2]);
this.loginState = infoArray[3];
}
if(new Date().getTime() - getSessionTime().getTime() > LoginInfo.COOKIE_TIME){
CookieUtil.delCookie(resp, LoginInfo.COOKIE_NAME);
return false;
}
return true;
}
protected void saveCookie(){
setSessionTime(new Date());
setLoginState("in");
CookieUtil.addCookie(resp, LoginInfo.COOKIE_NAME, toString(), "/");
}
public void clearCookie(){
setUserName("XX");
setUserPass("XX");
setSessionTime(new Date());
setLoginState("out");
CookieUtil.addCookie(resp, LoginInfo.COOKIE_NAME, toString(), "/");
}
@Override
public String toString() {
return DigestUtil.getBASE64(userName)+SEPARATION+DigestUtil.getBASE64(userPass)+SEPARATION+formateSessionTime()+SEPARATION+loginState;
}
private String formateSessionTime(){
SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
String timeStr =df.format(sessionTime);
return timeStr;
}
private Date buildDate(String sessionTime) {
SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
Date date = null;
try {
date = df.parse(sessionTime);
}catch (Exception ex){
System.out.println(ex.getMessage());
}
return date;
}
public Date getSessionTime() {
return sessionTime;
}
public void setSessionTime(Date sessionTime) {
this.sessionTime = sessionTime;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}
public String getLoginState() {
return loginState;
}
public void setLoginState(String loginState) {
this.loginState = loginState;
}
}
doLogin(),doLogout(),isSessionEmpty()必須在子類中實現(xiàn)實現(xiàn)
分別用來登錄系統(tǒng),注銷系統(tǒng),判斷是否登錄
ok,比較亂不懂的可以提問
有人要求Util的代碼,無語,貼出來吧
package net.heart.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class CookieUtil {
public static void addCookie(HttpServletResponse response,String name,String value,int maxAge){
try {
Cookie cookie=new Cookie(name,URLEncoder.encode(value, "utf-8"));
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getValue(HttpServletRequest request,String name){
String value=null;
Cookie[] cookies=request.getCookies();
if(cookies!=null){
for(Cookie cookie:cookies){
if(name.equals(cookie.getName())){
try {
value=URLDecoder.decode(cookie.getValue(),"utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
return value;
}
public static void delCookie(HttpServletResponse response,String name){
Cookie cookie=new Cookie(name,"");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}