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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

shiro 删除用户session_我的shiro之旅: 十二 shiro 踢出用户(同一用户只能一处登录)...

發布時間:2024/1/23 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 shiro 删除用户session_我的shiro之旅: 十二 shiro 踢出用户(同一用户只能一处登录)... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

看了一下官網,沒有找到關于如何控制同一用戶只能一處登錄的介紹,網上也沒有找到相關的文章。可能有些人會記錄用戶的登錄信息,然后達到踢出用戶的效果。這里介紹一個更簡單的方法。

如果我們跟shiro的源碼,我們可以看到。當用戶登錄成功 后,shiro會把用戶名放到session的attribute中,key為 DefaultSubjectContext_PRINCIPALS_SESSION_KEY,這個key的定義是在shiro的 org.apache.shiro.subject.support.DefaultSubjectContext中,這個類有三個public的靜態屬 性,其他都為private。其中PRINCIPALS_SESSION_KEY這個屬性記錄的是用戶名,而 AUTHENTICATED_SESSION_KEY屬性記錄的是用戶認證,當用戶登錄成功后,這個attribute的值是true。

曾經我想把AUTHENTICATED_SESSION_KEY這個 attribute的值設置為false,表示用戶是退出狀態,這樣達到退出用戶的目的,不過沒有成功,shiro判斷用戶是否是登錄狀態并不從這里判 斷。不過既然我們可以通過用戶名可以找到用戶對應的session,也很容易將該session刪除,讓用戶重新建立一個新的sesison。這里給出一 個幫助類,帶有跳出用戶的功能。

package com.concom.security.infrastructure.helper;

import java.util.Collection;

import org.apache.commons.lang.StringUtils;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.session.Session;

import org.apache.shiro.session.mgt.eis.SessionDAO;

import org.apache.shiro.subject.PrincipalCollection;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.subject.support.DefaultSubjectContext;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.concom.lang.helper.TimeHelper;

import com.concom.security.application.memcache.CurrentUserMemcacheService;

import com.concom.security.application.user.UserService;

import com.concom.security.domain.user.User;

/**

* @author Dylan

* @time 2013-8-12

*/

public class ShiroSecurityHelper {

private final static Logger log = LoggerFactory.getLogger(ShiroSecurityHelper.class);

private static UserService userService;

private static CurrentUserMemcacheService currentUserMemcacheService;

private static SessionDAO sessionDAO;

/**

* 把user放到cache中

*

* @param user

*/

public static void setUser(User user) {

currentUserMemcacheService.save(user);

}

/**

* 清除當前用戶的緩存

*/

public static void clearCurrentUserCache() {

if (hasAuthenticated()) {

currentUserMemcacheService.remove(getCurrentUsername());

}

}

/**

* 從cache拿當前user

*

* @return

*/

public static User getCurrentUser() {

if (!hasAuthenticated()) {

return null;

}

User user = currentUserMemcacheService.get(getCurrentUsername());

try {

if (null == user) {

user = userService.getByUsername(getCurrentUsername());

ShiroSecurityHelper.setUser(user);

}

return user;

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 獲得當前用戶名

*

* @return

*/

public static String getCurrentUsername() {

Subject subject = getSubject();

PrincipalCollection collection = subject.getPrincipals();

if (null != collection && !collection.isEmpty()) {

return (String) collection.iterator().next();

}

return null;

}

/**

*

* @return

*/

public static Session getSession() {

return SecurityUtils.getSubject().getSession();

}

/**

*

* @return

*/

public static String getSessionId() {

Session session = getSession();

if (null == session) {

return null;

}

return getSession().getId().toString();

}

/**

* @param username

* @return

*/

public static Session getSessionByUsername(String username){

Collection sessions = sessionDAO.getActiveSessions();

for(Session session : sessions){

if(null != session && StringUtils.equals(String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)), username)){

return session;

}

}

return null;

}

/**踢除用戶

* @param username

*/

public static void kickOutUser(String username){

Session session = getSessionByUsername(username);

if(null != session && !StringUtils.equals(String.valueOf(session.getId()), ShiroSecurityHelper.getSessionId())){

ShiroAuthorizationHelper.clearAuthenticationInfo(session.getId());

log.info("############## success kick out user 【{}】 ------ {} #################", username,TimeHelper.getCurrentTime());

}

}

/**

* @param userService

* @param currentUserMemcacheService

* @param sessionDAO

*/

public static void initStaticField(UserService userService,CurrentUserMemcacheService currentUserMemcacheService,SessionDAO sessionDAO){

ShiroSecurityHelper.userService = userService;

ShiroSecurityHelper.currentUserMemcacheService = currentUserMemcacheService;

ShiroSecurityHelper.sessionDAO = sessionDAO;

}

/**

* 判斷當前用戶是否已通過認證

* @return

*/

public static boolean hasAuthenticated() {

return getSubject().isAuthenticated();

}

private static Subject getSubject() {

return SecurityUtils.getSubject();

}

}

再通過spring注入幫助類需要的靜態屬性。

讀者可以不關注userService,currentUserMemcacheService,其中踢出功能用到了SessionDAO,定義可能看我的shiro之旅: 七 shiro session 共享,文章里的spring配置文件有介紹,這里不再作描述。從這個類名我們就可以猜想到,這個類是用戶管理session的。ShiroAuthorizationHelper這個幫助類在我的shiro之旅:

九 shiro 清理緩存的權限信息這篇文章介紹到。通過用戶名使用用戶對應的session,然后將該session刪除,這個kickOutUser方法應該在用戶登錄之前調用。

session刪除后,當用戶再請求服務器時,服務端shiro會拋

出there is no

session的異常,然后從新為請求建立一個新的session,就像用戶很長時間沒有點擊瀏覽器,shiro的定時器定時將失效的session清除

的時候也拋出這個異常一樣。不過這個對用戶是透明的,對用戶的體驗沒有影響。

這是其中的一種方式,也許有更好的實現方式。如果讀者有更好的實現方式,希望能與我分享。

總結

以上是生活随笔為你收集整理的shiro 删除用户session_我的shiro之旅: 十二 shiro 踢出用户(同一用户只能一处登录)...的全部內容,希望文章能夠幫你解決所遇到的問題。

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