由于项目需求要实现单点登出需要在网上找了N久终于实现单点登出。
使用cas-server-core-3.3.3.jar(CAS Server 3.3.3)
使用cas-client-core-3.1.3.jar(CAS Client 3.1.3)
项目结合CAS SpringSecurity SSH
普通项目(没有结合Spring Security)的可以在web.xml中加入如下代码
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>
在我们的项目中由于结合了SpringSecurity 可以将filter加入到spring Security过滤链中,也可以直接向上面的一样加入web.xml中
首先在web.xml中加入监听器。
<!-- single sign out -->
<listener>
<listener-class>
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>
<!-- single sign out -->
然后把filter加入到spring Security过滤链中
package check;
import java.io.IOException;
import java.util.Enumeration;
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.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.session.HashMapBackedSessionMappingStorage;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.jasig.cas.client.util.AbstractConfigurationFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
public final class SingleSignOutFilter extends AbstractConfigurationFilter
{
private String artifactParameterName;
private static SessionMappingStorage SESSION_MAPPING_STORAGE = new HashMapBackedSessionMappingStorage();
private static Log log = LogFactory.getLog(SingleSignOutFilter.class);
public SingleSignOutFilter()
{
this.artifactParameterName = "ticket";
}
public void init(FilterConfig filterConfig)
throws ServletException
{
setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
init();
}
public void init() {
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
CommonUtils.assertNotNull(SESSION_MAPPING_STORAGE, "sessionMappingStorage cannote be null.");
}
public void setArtifactParameterName(String artifactParameterName) {
this.artifactParameterName = artifactParameterName;
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final String logoutRequest = CommonUtils.safeGetParameter(request, "logoutRequest");
Enumeration ff = request.getParameterNames();
String a = request.getQueryString();
if (CommonUtils.isNotBlank(logoutRequest)) {
final String sessionIdentifier = XmlUtils.getTextForElement(logoutRequest, "SessionIndex");
if (CommonUtils.isNotBlank(sessionIdentifier)) {
final HttpSession session = SESSION_MAPPING_STORAGE.removeSessionByMappingId(sessionIdentifier);
if (session != null) {
String sessionID = session.getId();
try {
session.invalidate();
} catch (final IllegalStateException e) {
}
}
}
}
else{
final String artifact = CommonUtils.safeGetParameter(request, this.artifactParameterName);
final HttpSession session = request.getSession(false);
if (CommonUtils.isNotBlank(artifact) && session!=null) {
try {
SESSION_MAPPING_STORAGE.removeBySessionById(session.getId());
} catch (final Exception e) {
}
SESSION_MAPPING_STORAGE.addSessionById(artifact, session);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void setSessionMappingStorage(SessionMappingStorage storage) {
SESSION_MAPPING_STORAGE = storage;
}
public static SessionMappingStorage getSessionMappingStorage() {
return SESSION_MAPPING_STORAGE;
}
public void destroy()
{
}
}
完成。
这样即可实现单点登出。(所有java应用的单点退出)
1)这样实现的效果是在登出的时候CAS Server 分发给各个客户端让各个客户端都登出,这个得让FIlter来获取,例子:一个index页面有两个链接一个指向java应用,一个指向php应用在java应用加filter 后能做出相应的动作退出动作,而对于php自己没加任何filter就没有退出。所以也得写个filter。
2)由于我们点击退出的时候请求CAS Server 而后Server分发任务让每个应用退出的消息,java程序通过filter来执行退出。PHP提供了一个phpCAS::handleLogoutRequests()来检验服务器发来的信息,
具体我们可以把这个代码放在phpbb3/include/function.php中的点击事件里面代码如下:
if(!$admin && CAS_ENABLE){
// initialize phpCAS
phpCAS::client(CAS_VERSION_2_0, CAS_SERVER_HOSTNAME, CAS_SERVER_PORT, CAS_SERVER_APP_NAME);
phpCAS::setNoCasServerValidation();
// force CAS authentication
phpCAS::handleLogoutRequests();//加的去看看有没有服务器端发出注销消息。
phpCAS::forceAuthentication();