日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CAS单点登出,调整CAS源码,实现前后端分离单点登出、清除redis、shiro登录状态

發布時間:2024/1/1 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CAS单点登出,调整CAS源码,实现前后端分离单点登出、清除redis、shiro登录状态 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前端點擊“登出”按鈕,跳轉到CAS的登出。

CAS默認配置了單點登出,在登出后,會向所有客戶端系統發送這個用戶登出的報文。

各客戶端系統有責任接收并處理這個用戶登出的報文,然后在注銷該用戶會話在本客戶端的信息。

若不進行 #CAS配置客戶端地址#客戶端后端 ,則網頁里的登出按鈕點擊之后就無法通知其他客戶端系統登出。

目前使用了客戶端集成CAS源碼并修改的方法,來對客戶端做了Filter接收CAS登出請求之后的處理。
有悖于CAS的建議"不要修改CAS源碼"。待以后再研究看有沒有什么優化方法。

CAS配置客戶端地址

??CAS的單點登出是默認啟用的。
??CAS向客戶端發送地址,默認為客戶端請求的URL。但該請求的URL是客戶端的前端地址(含端口),CAS需要向客戶端的后端發送請求。因此需要對對CAS配置客戶端的指定地址。

??CAS 對客戶端信息的存儲在/services/目錄下,這里配置jl-iam-client的信息,文件命名為iam-client-10000003.json,內容如下。
??其中

  • @class - 按默認填寫
  • serviceId - 正則表達式匹配客戶端請求到CAS的來源URL,這里是前端的地址。因為請求都是從前端window.location.href過來的。
  • name - 客戶端名稱
  • id - ID,不要重復
  • description - 描述
  • evalutionOrder - 順序。一個客戶端的URL匹配成功了多個客戶端信息,以evalutionOrder最小的來處理。
  • logoutType - 登出類型??商?#34;BACK_CHANNEL"或"FRONT_CHANNEL",分別對應后端方式、前端方式。以不配置此項,則默認是"BACK_CHANNEL"。這里使用后端方式登出。
  • logoutUrl - 登出URL。如果不配置此項,CAS會向來源URL發送登出請求。在前后端分離的結構下,來源是前端地址,與后端地址不同。因此需要配置該項為后端地址

該地址最后為上下文根+“/”。然后不需再有其他字符。
上下文根一定要有!
上下文根后的"/"一定要有!
否則無法訪問到客戶端的Filter。另外,由于配置單點登出的Filter過濾URL樣式為"/*",因此后面不需要加其他字符。

{"@class" : "org.apereo.cas.services.RegexRegisteredService","serviceId" : "^(http)://192.168.2.111:8086.*","name" : "iam-client","id" : 10000003,"description" : "iam-client info","evaluationOrder" : 1,"logoutType" : "BACK_CHANNEL","logoutUrl" : "http://192.168.2.111:8082/iam-client/" }

客戶端后端

配置Filter

??客戶端(jl-iam-client)需要配置Filter來接收CAS單點登出的請求。
??接收請求后需要做這些處理:記錄登出日志、刪除Redis信息、調用Shiro的logout。

??在cas-client-core中的SingleSignOutFilter清空了Session,但是并沒有其他處理。
??由于目前還沒有找到追增處理的方法,因此現在將cas-client-core的SingleSignOutFilter以及SingleSignOutHandler重寫在工程里,對登出處理做了一些定制。

??客戶端使用springboot構建。使用@WebFilter 注解,將定制的SingleSignOutFilter注冊為Filter。

注意注解的參數配置。

@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "casServerUrlPrefix", value = "https://cas.example.com:8443/cas") }) public class SingleSignOutFilter extends AbstractConfigurationFilter {

設置回調方法

??注銷時刪除Session的方法,是在SingleSignOutHandler的destroySession()方法中執行的,并且CAS的票據ticket也是在該方法中解析到的。
??在SingleSignOutHandler中,設置一個回調方法,在destroySession()方法中調用。

回調方法定義

額外登出策略類 ExtraLogoutStrategy.java

public interface ExtraLogoutStrategy {/*** 登出方法* @param ticket CAS票據*/void logout(String ticket); }

額外登出策略實現類 CasLogoutStrategy.java

public class CasLogoutStrategy implements ExtraLogoutStrategy {@Autowiredprivate RedisUtil redisUtil;@Autowiredprivate ISysBaseAPI sysBaseAPI;@Resourceprivate BaseCommonService baseCommonService;@Overridepublic void logout(String ticket) {String token = redisUtil.get(CommonConstant.PRIFIX_CAS_TICKET + ticket).toString();String username = JwtUtil.getUsername(token);LoginUser sysUser = sysBaseAPI.getUserByName(username);if(sysUser != null) {baseCommonService.addLog("用戶名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null,sysUser);log.info(" 用戶名: "+sysUser.getRealname()+",退出成功!");//清空用戶登錄CAS ticket緩存redisUtil.del(CommonConstant.PRIFIX_CAS_TICKET + ticket);//清空用戶登錄Token緩存redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);//清空用戶登錄Shiro權限緩存redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());//清空用戶的緩存信息(包括部門信息),例如sys:cache:user::<username>redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));//調用shiro的logoutSecurityUtils.getSubject().logout();}} }

調整CAS源碼 SingleSignOutHandler.java

/** 額外登出處理策略回調類 **/private ExtraLogoutStrategy extraLogoutStrategy; /*** 設置額外登出策略* @param extraLogoutStrategy 額外登出策略*/public void setExtraLogoutStrategy(ExtraLogoutStrategy extraLogoutStrategy) {this.extraLogoutStrategy = extraLogoutStrategy;}

回調方法設置

修改部分 調整CAS源碼 SingleSignOutFilter.java

@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "casServerUrlPrefix", value = "https://iamlocal.90tech.cn:8443/cas") }) @Qualifier("casLogoutStrategy")@Autowiredprivate ExtraLogoutStrategy casLogoutStrategy; HANDLER.setExtraLogoutStrategy(casLogoutStrategy);

完整類 SingleSignOutFilter.java

@Slf4j @WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "casServerUrlPrefix", value = "https://iamlocal.90tech.cn:8443/cas") }) public class SingleSignOutFilter extends AbstractConfigurationFilter {private static final SingleSignOutHandler HANDLER = new SingleSignOutHandler();private final AtomicBoolean handlerInitialized = new AtomicBoolean(false);@Qualifier("casLogoutStrategy")@Autowiredprivate ExtraLogoutStrategy casLogoutStrategy;@Overridepublic void init(final FilterConfig filterConfig) throws ServletException {log.info("SingleSignOutFilter init.");super.init(filterConfig);if (!isIgnoreInitConfiguration()) {setArtifactParameterName(getString(ConfigurationKeys.ARTIFACT_PARAMETER_NAME));setLogoutParameterName(getString(ConfigurationKeys.LOGOUT_PARAMETER_NAME));setRelayStateParameterName(getString(ConfigurationKeys.RELAY_STATE_PARAMETER_NAME));setLogoutCallbackPath(getString(ConfigurationKeys.LOGOUT_CALLBACK_PATH));HANDLER.setArtifactParameterOverPost(getBoolean(ConfigurationKeys.ARTIFACT_PARAMETER_OVER_POST));HANDLER.setEagerlyCreateSessions(getBoolean(ConfigurationKeys.EAGERLY_CREATE_SESSIONS));HANDLER.setExtraLogoutStrategy(casLogoutStrategy);}HANDLER.init();handlerInitialized.set(true);}

回調方法調用

修改部分 調整CAS源碼 SingleSignOutHandler.destroySession()

if (this.extraLogoutStrategy != null) {this.extraLogoutStrategy.logout(token);}

完整方法 SingleSignOutHandler.destroySession()

/*** Destroys the current HTTP session for the given CAS logout request.** @param request HTTP request containing a CAS logout message.*/private void destroySession(final HttpServletRequest request) {String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters);if (CommonUtils.isBlank(logoutMessage)) {logger.error("Could not locate logout message of the request from {}", this.logoutParameterName);return;}if (!logoutMessage.contains("SessionIndex")) {logoutMessage = uncompressLogoutMessage(logoutMessage);}logger.trace("Logout request:\n{}", logoutMessage);final String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");if (CommonUtils.isNotBlank(token)) {final HttpSession session = this.sessionMappingStorage.removeSessionByMappingId(token);if (session != null) {final String sessionID = session.getId();logger.debug("Invalidating session [{}] for token [{}]", sessionID, token);try {session.invalidate();} catch (final IllegalStateException e) {logger.debug("Error invalidating session.", e);}this.logoutStrategy.logout(request);if (this.extraLogoutStrategy != null) {this.extraLogoutStrategy.logout(token);}}}}

CAS ticket緩存

??在CAS代碼處理中,是以接收到的ticket為憑據的。我的系統通過緩存token實現認證。
??所以,為了CAS能與系統成功交互,需要將CAS ticket緩存,并與系統中的token建立關聯。

上文 #額外登出策略實現類 CasLogoutStrategy.java 中,已經通過CAS ticket緩存取到了token,并將ticket和token的緩存數據都刪除了。

修改部分

// 設置超時時間redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);redisUtil.set(CommonConstant.PRIFIX_CAS_TICKET + ticket, token);redisUtil.expire(CommonConstant.PRIFIX_CAS_TICKET + ticket, JwtUtil.EXPIRE_TIME*2 / 1000);

總結

以上是生活随笔為你收集整理的CAS单点登出,调整CAS源码,实现前后端分离单点登出、清除redis、shiro登录状态的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。