/*
* Created on 2005-9-15
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package com.suncode.web.filter;
import java.io.IOException;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
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;
/**
* @ author jiang 单点登录过滤器 实现多个web应用的单点登录 需要在所指定的singleSignOnPage设置cookie或session
* 目前只支持同一个域名下的多应用
*
* 2005-12-23 增加checkMode参数,可选择cookie,session两种方式.
* 2005-10-28 增加allowRoles参数,可以指定允许访问的角色.
*/
public class SingleSignOnFilter implements Filter {
// 输入多个参数值时的分割符
private final String DELIMITER = ",";
private final String MODE_COOKIE = "cookie";
private final String MODE_SESSION = "session";
protected FilterConfig filterConfig = null;
// 检查方式,目前支持cookie和session两种
// 其中session方式只能用在一个应用的情况下,cookie支持同一域名下多个应用,默认为cookie.
protected String checkMode = null;
// 是否禁用该Filter
protected boolean disabled = false;
// 允许访问的角色,以DELIMITER指定的分割符隔开,"*"表示允许所有登录的角色
protected String allowRoles = "*";
// 由allowRoles提取出的List
protected List allowRoleList = null;
// 登录用户id的cookie键值,单点登录的多个应用中,该值必须相同
protected String cookieKeyUid = null;
protected String cookieKeyPwd = null;
protected String cookieKeyRole = null;
// 不进行过滤的页面,以DELIMITER指定的分割符隔开
// 如"/search/prod.jsp,/index.jsp"
protected String excludePages = null;
// 由excludePages提取出的List
protected List excludePageList = null;
protected String requestKeyFrom = null; // 预留
protected String requestKeySiteId = null; // 预留
// 登录用户id的session键值,各应用中该值可以不同
protected String sessionKeyUid = null;
protected String sessionKeyPwd = null;
protected String sessionKeyRole = null;
// 单点登录页面的完整url
protected String singleSignOnPage = null;
// 当前请求的用户信息
private String uid = null;
private String pwd = null;
private String role = null;
// required
/*
* (non-Javadoc)
*
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.singleSignOnPage = filterConfig
.getInitParameter("singleSignOnPage");
this.checkMode = filterConfig.getInitParameter("checkMode");
if (isEmpty(this.checkMode)) {
this.checkMode = this.MODE_COOKIE;// set to default, check by
// cookie.
}
this.cookieKeyUid = filterConfig.getInitParameter("cookieKeyUid");
this.cookieKeyPwd = filterConfig.getInitParameter("cookieKeyPwd");
this.cookieKeyRole = filterConfig.getInitParameter("cookieKeyRole");
this.allowRoles = filterConfig.getInitParameter("allowRoles");
if (isEmpty(this.allowRoles))
this.allowRoles = "*"; // set to default, allow all roles.
this.allowRoleList = split(this.allowRoles, this.DELIMITER);
this.excludePages = filterConfig.getInitParameter("excludePages");
this.excludePageList = split(this.excludePages, this.DELIMITER);
this.requestKeyFrom = filterConfig.getInitParameter("requestKeyFrom");
this.requestKeySiteId = filterConfig
.getInitParameter("requestKeySiteId");
this.sessionKeyUid = filterConfig.getInitParameter("sessionKeyUid");
this.sessionKeyPwd = filterConfig.getInitParameter("sessionKeyPwd");
this.sessionKeyRole = filterConfig.getInitParameter("sessionKeyRole");
String value = filterConfig.getInitParameter("disabled");
if (value == null)
this.disabled = false;
else if (value.equalsIgnoreCase("true"))
this.disabled = true;
else if (value.equalsIgnoreCase("yes"))
this.disabled = true;
else
this.disabled = false;
}
/*
* (non-Javadoc)
*
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (!disabled && !isEmpty(this.singleSignOnPage)) {
doFilter(request, response);
}
chain.doFilter(request, response);
}
public void doFilter(ServletRequest req, ServletResponse res)
throws IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 在ignore()前执行,保证不过滤的页面,也能从session获取用户信息
getUserData(request);
if (ignore(request)) {
return;
}
//用户未登录,或者角色不合法
if (isEmpty(uid) || !isValidRole(role)) {
// 重定向到单点登录页面
response.sendRedirect(getSingleSignOnUrl(request));
}
}
/*
* (non-Javadoc)
*
* @see javax.servlet.Filter#destroy()
*/
public void destroy() {
this.allowRoles = null;
this.allowRoleList = null;
this.checkMode = null;
this.cookieKeyUid = null;
this.cookieKeyPwd = null;
this.excludePageList = null;
this.excludePages = null;
this.filterConfig = null;
this.requestKeyFrom = null;
this.requestKeySiteId = null;
this.sessionKeyUid = null;
this.sessionKeyPwd = null;
this.singleSignOnPage = null;
}
public String getCookieValue(HttpServletRequest request, String cookieName) {
String value = null;
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return value;
}
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
String name = cookie.getName();
if (name.equals(cookieName)) {
value = cookie.getValue();
break;
}
}
return value;
}
public String getSingleSignOnUrl(HttpServletRequest request) {
String url = "";
if (!isEmpty(this.singleSignOnPage)) {
url = this.singleSignOnPage;
} else {
return url;
}
// TODO urlEncoding
if (!isEmpty(this.requestKeyFrom)) {
url += "?" + this.requestKeyFrom + "="
+ request.getRequestURL().toString();
}
return url;
}
protected List split(String s, String delimiter) {
List lst = new Vector();
if (isEmpty(s))
return lst;
StringTokenizer st = new StringTokenizer(s, delimiter);
while (st.hasMoreTokens()) {
lst.add(st.nextToken());
}
return lst;
}
protected boolean isEmpty(String s) {
return (s == null || s.length() < 1);
}
/**
* 根据checkMode,从cookie或session中读取用户数据,记录在filter的字段中. 并根据需要,将用户数据存入session中.
*
* @param request
*/
protected void getUserData(HttpServletRequest request) {
if (checkMode.equalsIgnoreCase(this.MODE_SESSION)) {// 从session中取用户数据
if (!isEmpty(this.sessionKeyUid))
uid = (String) request.getSession().getAttribute(
this.sessionKeyUid);
if (!isEmpty(this.sessionKeyPwd))
pwd = (String) request.getSession().getAttribute(
this.sessionKeyPwd);
if (!isEmpty(this.sessionKeyRole))
role = (String) request.getSession().getAttribute(
this.sessionKeyRole);
} else {// 默认从cookie中取用户数据
if (!isEmpty(this.cookieKeyUid))
this.uid = getCookieValue(request, this.cookieKeyUid);
if (!isEmpty(this.cookieKeyPwd))
this.pwd = getCookieValue(request, this.cookieKeyPwd);
if (!isEmpty(this.cookieKeyRole))
this.role = getCookieValue(request, this.cookieKeyRole);
copyUserDataToSession(request);
}
}
/**
* 将filter字段中记录的用户数据copy到session中.
*
* @param request
* @return
*/
protected void copyUserDataToSession(HttpServletRequest request) {
if (!isEmpty(this.uid)) {
if (!isEmpty(this.sessionKeyUid))
request.getSession().setAttribute(this.sessionKeyUid, uid);
if ((this.pwd != null) && (!isEmpty(this.sessionKeyPwd))) { // pwd可为空串
request.getSession().setAttribute(this.sessionKeyPwd, pwd);
}
if ((this.role != null) && (!isEmpty(this.sessionKeyRole))) {
request.getSession().setAttribute(this.sessionKeyRole, role);
}
}
}
protected boolean ignore(HttpServletRequest request) {
boolean result = false;
if (excludePageList == null || excludePageList.isEmpty())
return result;
String page = request.getServletPath();
//System.out.println(page);
if (excludePageList.contains(page)) {
result = true;
}
return result;
}
protected boolean isValidRole(String role) {
boolean isValid = false;
if (this.allowRoleList.isEmpty() || this.allowRoleList.contains("*")
|| this.allowRoleList.contains(role))
return true;
return isValid;
}
public static void main(String args[]) {
List lst = new Vector();
System.out.println("main().");
StringTokenizer st = new StringTokenizer("", ",");
while (st.hasMoreTokens()) {
lst.add(st.nextToken());
System.out.println("add one token.");
}
}
}