Cas 实现单点登录的实际应用
根据实际项目开发过程对Cas单点登录做了梳理,在吸收了前辈们的宝贵经验的基础上记录全套开发过程,如下
其他是有这样一个数据库(casserver)一张数据表(tsys_user)
com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc:sqlserver://localhost:1435; DatabaseName=casserver
sa
sa
public class AlQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
//@NotNull
private String sql;
protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
final String id = getPrincipalNameTransformer().transform(credentials.getUsername());
final String password = credentials.getPassword();
try {
final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, id);
System.out.print("Username:" + id);
System.out.print("dbPassword:" + dbPassword);
return MD5.verifyPassword(MD5.getMD5ofStr(password)+id, dbPassword);
} catch (final IncorrectResultSizeDataAccessException e) {
return false;
}
}
/**
* @param sql The sql to set.
*/
public void setSql(final String sql) {
this.sql = sql;
}
}
客户端的jar,如cas-client-core-3.2.1.jar引入到web应用程序的classpath中
配置web.xml文件, 主要是添加过滤器拦截通信, 下面的实例代码, 假设web应用程序的端口是9988
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
CAS Single Sign Out Filter
org.jasig.cas.client.session.SingleSignOutFilter
CAS Single Sign Out Filter
/*
CAS Filter
org.jasig.cas.client.authentication.AuthenticationFilter
casServerLoginUrl
http://localhost:8080/casweb3.5.2/login
serverName
http://localhost:9988
CAS Filter
/*
CAS Validation Filter
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
casServerUrlPrefix
http://localhost:8080/casweb3.5.2
serverName
http://localhost:9988
CAS Validation Filter
/*
CAS HttpServletRequest Wrapper Filter
org.jasig.cas.client.util.HttpServletRequestWrapperFilter
CAS HttpServletRequest Wrapper Filter
/*
CAS Assertion Thread Local Filter
org.jasig.cas.client.util.AssertionThreadLocalFilter
CAS Assertion Thread Local Filter
/*
casSetUserAdapterFilter
casSetUserAdapterFilter
com.aolong.eip.portal.sys.servlet.CasSetUserAdapterFilter
casSetUserAdapterFilter
/*
注意这些配置应该尽量放在其他过滤器前面,比如Struts的配置, 如果顺序搞错,它的过滤器想不会起作用,这一点是容易被忽略的
自定义的过滤器代码:
public class CasSetUserAdapterFilter implements Filter {
@Override
public void init(FilterConfig paramFilterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest paramServletRequest,
ServletResponse paramServletResponse, FilterChain paramFilterChain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) paramServletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) paramServletResponse;
HttpSession session = httpRequest.getSession();
//_const_cas_assertion_是CAS中存放登录用户名的session标志
Object object = session.getAttribute("_const_cas_assertion_");
Object userId = session.getAttribute(SessionUtils.SKEY_USERID);
if (object != null && ((userId == null) || ("".equals(userId.toString())))) {
Assertion assertion = (Assertion) object;
String loginName = assertion.getPrincipal().getName();
ILoginService loginService = (ILoginService) SpringContextUtil.getBean("loginService");
loginService.ssoLogin(loginName, httpRequest, httpResponse);
if (loginPage >= 0)
{
session.setAttribute(SessionUtils.SKEY_LOGINPAGE, this.loginPage);
}
}
paramFilterChain.doFilter(paramServletRequest, paramServletResponse);
}
protected void setLoginPage(int iLoginPage)
{
this.loginPage = iLoginPage;
}
@Override
public void destroy() {
}
private int loginPage = -1;
}
CAS3.4版本已经很好的支持了单点注销功能
假设环境如下: