书接上文,上文介绍了若依分离版集成CAS实现单点登录,并解决了登录后的跳转页面,本文将解决单点登出问题。
奴友会发现上文的集成教程中,单点登出是存在缺陷的:通过若依系统登出没问题,但是直接通过CAS或其他接入系统登出,若依不能正常登出,这是因为若依前端已经持有了token,且token在后端还处于正常状态,自然可以正常访问。
一、单点登出
1、修改TokenService,增加“删除用户登录信息”方法。
/**
* cas 删除用户身份信息
*/publicvoid delClaimsLoginUser(String token)
{
if (StringUtils.isNotEmpty(token))
{
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
redisCache.deleteObject(userKey);
}
}
2、添加CustomSessionMappingStorage,该类负责接收CAS服务器发出的登出信息,并删除对应的token。
import com.ruoyi.common.constant.Constants;
import com.ruoyi.framework.web.service.TokenService;
import org.apache.catalina.session.StandardSessionFacade;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
/**
* @author LuoFei
* @className: CustomSessionMappingStorage
* @projectName RuoYi-Vue-master
* @description: TODO
* @date 2022/4/28 12:56
*/@ComponentpublicclassCustomSessionMappingStorageimplementsSessionMappingStorage{
privatefinal Map<String, HttpSession> MANAGED_SESSIONS = new HashMap();
privatefinal Map<String, String> ID_TO_SESSION_KEY_MAPPING = new HashMap();
privatefinal Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowiredprivate TokenService tokenService;
public CustomSessionMappingStorage() {
}
@Overridepublic synchronized void addSessionById(String mappingId, HttpSession session) {
this.ID_TO_SESSION_KEY_MAPPING.put(session.getId(), mappingId);
this.MANAGED_SESSIONS.put(mappingId, session);
}
@Overridepublic synchronized void removeBySessionById(String sessionId) {
this.logger.debug("Attempting to remove Session=[{}]", sessionId);
String key = (String)this.ID_TO_SESSION_KEY_MAPPING.get(sessionId);
if (this.logger.isDebugEnabled()) {
if (key != null) {
this.logger.debug("Found mapping for session. Session Removed.");
} else {
this.logger.debug("No mapping for session found. Ignoring.");
}
}
this.MANAGED_SESSIONS.remove(key);
this.ID_TO_SESSION_KEY_MAPPING.remove(sessionId);
}
@Overridepublic synchronized HttpSession removeSessionByMappingId(String mappingId) {
StandardSessionFacade session = (StandardSessionFacade) this.MANAGED_SESSIONS.get(mappingId);
if (session != null) {
this.removeBySessionById(session.getId());
try {
String token = (String) session.getAttribute(Constants.CAS_TOKEN);
tokenService.delClaimsLoginUser(token);
} catch (IllegalStateException e) {
this.logger.error("已成功登出");
}
}
return session;
}
}
3、修改SecurityConfig单点登出过滤器。
@Autowiredprivate CustomSessionMappingStorage customSessionMappingStorage;
/**
* 单点登出过滤器
*/@Beanpublic SingleSignOutFilter singleSignOutFilter(){
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
//singleSignOutFilter.setLogoutCallbackPath(casProperties.getWebUrl());
singleSignOutFilter.setSessionMappingStorage(customSessionMappingStorage);
singleSignOutFilter.setIgnoreInitConfiguration(true);
return singleSignOutFilter;
}
其他系统向CAS服务发生登出请求后,CAS服务会向接入系统发出登出的通知信息,单点登出过滤器会将登出请求交给customSessionMappingStorage处理,customSessionMappingStorage删除对应等token,完成单点登出。