【IT168技术文档】
最近在研究Yale CAS,因为其Java客户端采用Filter来实现单点登录SSO(其他客户端像ASP,PHP应该也类似),以便当过滤器匹配到受保护的URL时,若发现用户没有登录,就重定向到登录中心进行登录。在Tapestry 4中以及Tapestry 3中,URL的层级结构都需要配置层级式的页面逻辑名、如admin/editPerson.page,Tapestry 5默认出现了层级结构,但还没到版本发布的时候,在此就Tapestry 4应用,通过一种变相的形式实现其SSO过滤器,主要应用于先前没有配置好层级结构的页面逻辑名且重构页面逻辑名较难的应用。
环境:cas-server-3.0.7-rc2 cas-client-java-2.1.1 Tapestry 4 Tomcat 5.0.28
第一步:扩展org.apache.tapestry.ApplicationServlet。
package com.demo.sso;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.apache.tapestry.ApplicationServlet;
/**//**
* 功能描述: 重载初始化函数,保存Tapestry4注册类对象的key到全局application对象中
*
* @author iroyce Created on d2007-4-29w
*/
public class SSOApplicationServlet extends ApplicationServlet ...{
private static final long serialVersionUID = -1234455546455555444L;
/**//** Tapestry4注册类(RegistryImpl)对象、也就是infrastructure, 其在application map变量里的key前缀*/
private static final String REGISTRY_KEY_PREFIX = "org.apache.tapestry.Registry:";
/**//** Tapestry4注册类(RegistryImpl)对象key*/
public static String REGISTRY_KEY = null;
public void init(ServletConfig config) throws ServletException ...{
super.init(config);
String name = config.getServletName();
REGISTRY_KEY = REGISTRY_KEY_PREFIX + name;
}
}
第二步:扩展cas-client-java-2.1.1中的edu.yale.its.tp.cas.client.filter.CASFilter。
package com.demo.sso;
![]()
import java.io.IOException;
import java.util.StringTokenizer;
![]()
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 org.apache.hivemind.impl.RegistryImpl;
import org.apache.tapestry.services.ApplicationGlobals;
import org.apache.tapestry.services.ServiceConstants;
import org.apache.tapestry.spec.IApplicationSpecification;
![]()
import edu.yale.its.tp.cas.client.filter.CASFilter;
![]()
/**//**
* 功能描述: CAS java client在Tapestry 4 下的扩展
*
* @author iroyce Created on d2007-4-30
*/
![]()
public class MyCASFilter extends CASFilter ...{
![]()
/**//** 受保护的路径配置名,其值以空格或换行作为间隔*/
public final static String FILTERED_PATHS_INIT_PARAM = "com.demo.sso.filteredPaths";
![]()
/**//** 受保护的路径*/
private String filteredPaths = null;
![]()
/**//** Tapetry应用的配置*/
private static IApplicationSpecification spec = null;
![]()
public void init(FilterConfig config) throws ServletException ...{
super.init(config);
//配置受保护的路径
this.filteredPaths = config.getInitParameter(FILTERED_PATHS_INIT_PARAM);
}
![]()
![]()
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain fc) throws ServletException, IOException ...{
![]()
if (!(request instanceof HttpServletRequest))
throw new ServletException("CASFilter protects only HTTP resources");
![]()
HttpServletRequest hsr = (HttpServletRequest) request;
![]()
if (hsr.getSession() == null) ...{
fc.doFilter(request, response);
return;
}
![]()
//得到Tapestry的页面配置
if(spec==null)...{
RegistryImpl _registry = (RegistryImpl) hsr.getSession().getServletContext().getAttribute(
SSOApplicationServlet.REGISTRY_KEY);
![]()
ApplicationGlobals _globals = (ApplicationGlobals) _registry.getService(
"tapestry.globals.ApplicationGlobals", ApplicationGlobals.class);
![]()
this.spec = _globals.getSpecification();
}
![]()
//得到当前请求的页面名并判断是否是受保护的资源
if (spec != null) ...{
String pageName = hsr.getParameter(ServiceConstants.PAGE);
if(pageName==null)...{
String url = hsr.getRequestURI();
int start = url.lastIndexOf('/');
int end = url.lastIndexOf('.');
pageName = url.substring(start+1, end);
if(pageName==null)
pageName = "Home";
}
String pagePath = spec.getPageSpecificationPath(pageName);
![]()
StringTokenizer filteredPaths = new StringTokenizer(this.filteredPaths);
boolean isFilter = false;
while(filteredPaths.hasMoreTokens())...{
String filteredPath = filteredPaths.nextToken();
if(pagePath.indexOf(filteredPath)!=-1)...{
isFilter = true;
break;
}
}
![]()
//如果当前不是在拦截的目录之内
if(!isFilter)...{
fc.doFilter(request, response);
return;
}
![]()
}
//进入CAS client的SSO过程
super.doFilter(request, response, fc);
}
}
第三步:修改WEB-INF/web.xml配置。
<filter>
<filter-name>redirectfilter-name>
<filter-class>org.apache.tapestry.RedirectFilterfilter-class>
filter>
<filter-mapping>
<filter-name>redirectfilter-name>
<url-pattern>/url-pattern>
filter-mapping>
![]()
<filter>
<filter-name>CASFilterfilter-name>
<filter-class>com.demo.sso.MyCASFilterfilter-class>
<init-param>
<param-name>edu.yale.its.tp.cas.client.filter.loginUrlparam-name>
<param-value>https://www.royce.com:8443/cas/loginparam-value>
init-param>
![]()
<init-param>
<param-name>edu.yale.its.tp.cas.client.filter.validateUrlparam-name>
<param-value>https://www.royce.com:8443/cas/proxyValidateparam-value>
init-param>
![]()
<init-param>
<param-name>edu.yale.its.tp.cas.client.filter.serverNameparam-name>
<param-value>127.0.0.1:8080param-value>
init-param>
![]()
<init-param>
<param-name>com.demo.sso.filteredPathsparam-name>
<param-value>
admin/
pageadvisor/
param-value>
init-param>
filter>
![]()
![]()
<filter-mapping>
<filter-name>CASFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
![]()
![]()
<servlet>
<servlet-name>tshservlet-name>
<servlet-class>com.demo.sso.SSOApplicationServletservlet-class>
<load-on-startup>0load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>tshservlet-name>
<url-pattern>/appurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>tshservlet-name>
<url-pattern>*.pageurl-pattern>
servlet-mapping>