首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Spring security扩充自定义会话管理

2012-09-03 
Spring security扩展自定义会话管理控制用户重复登陆?springsecurity有控制单账号只能在一个地方登陆的功

Spring security扩展自定义会话管理

控制用户重复登陆?

springsecurity有控制单账号只能在一个地方登陆的功能,后登陆用户将踢掉前登陆用户;或者限制账号重复登陆,一个账号没有退出,另外一个人想用这个账号就登陆不上。?

现在我想根据原有的这些功能参考,做一个管理员可以将某正在session中的用户踢出系统的功能。便于管理员修改了登陆用户的权限或者部门设置后,强制让该用户重新登录。?

主要参考了如下两篇文章:?
http://www.family168.com/oa/springsecurity/html/ch214-smart-concurrent.html?
http://www.blogjava.net/beyondwcm/archive/2009/05/08/269545.html?

主要涉及的类如下(我自己的山寨理解):?
HttpSessionEventPublisher???????????? 监听session创建和销毁?
ConcurrentSessionFilter????????????????? 每次有http请求时校验,看你当前的session是否是过期的?
SessionRegistryImpl?????????????????????? 存放session中的信息,并做处理?
ConcurrentSessionControllerImpl???? 用户登入登出的控制?
SessionInformation?????? 存储session中信息的model?

先实现springsecurity文档上的,限制用户重复登陆,后登陆用户将前登陆用户冲掉 ,只需要在xml中配置如下:?
<authentication-manager alias="authenticationManager"?
session-controller-ref="currentController" />?
<beans:bean id="concurrentSessionFilter"?? />?
<beans:property name="sessionRegistry" ref="sessionRegistry" />?
<!-- 踢出的用户转向的页面-->?
<beans:property name="expiredUrl" value="/user/user.action" />?
<beans:property name="logoutHandlers">?
?? <beans:list>?
??? <beans:bean />?
??? <beans:bean?
???? value="e37f4b31-0c45-11dd-bd0b-0800200c9a66"/>?
???? <beans:property name="userDetailsService" ref="userDetailsService"/>?
??? </beans:bean>?
?? </beans:list>?
</beans:property>?
</beans:bean>?
<beans:bean id="sessionRegistry"?? />?
<beans:bean id="currentController"?
ref="sessionRegistry" />?
<!-- true限制不允许第二个用户登录,false第二个登陆用户踢掉前一个登陆用户 -->?
<beans:property name="exceptionIfMaximumExceeded" value="false" />?
<!-- 等第二种情况是,允许同时多少个用户同时登陆 -->?
<beans:property name="maximumSessions" value="2"/>?
</beans:bean>?

其中web.xml还需要添加:?
<!-- 登入和登出时对SessionRegistryImpl进行处理 -->?
<listener>?
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>?
</listener>?

?

提供管理员调用踢出用户?

配置文件基本上和(一)比没有做什么修改,只是不限制用户用同一账号登陆,所以配置maximumSessions为-1?
<beans:bean id="currentController"?
ref="sessionRegistry" />?
<beans:property name="exceptionIfMaximumExceeded"?
?? value="false" />?
<beans:property name="maximumSessions" value="-1"/>?
</beans:bean>?

其实要实现列表当前登陆的用户,并踢出用户,就是调用springsecurity的?
org.springframework.security.concurrent.SessionRegistryImpl?
就可以满足要求了,当然,用这个类来做踢出用户的功能,不是很好,不过也懒得去动这个源码了,由于mini-web的示例是struts2的,所以我就简单的写了个Action去调用这个类来操作,如果要用到公司的项目中,那还要放到controller里面去才行,SessionAction.java:?
package org.springside.examples.miniweb.web.user;?
import java.util.ArrayList;?
import java.util.List;?
import org.apache.struts2.config.ParentPackage;?
import org.apache.struts2.config.Result;?
import org.apache.struts2.config.Results;?
import org.apache.struts2.dispatcher.ServletActionRedirectResult;?
import org.springframework.security.concurrent.SessionInformation;?
import org.springframework.security.concurrent.SessionRegistry;?
import org.springside.modules.web.struts2.CRUDActionSupport;?
import org.springside.modules.web.struts2.SimpleActionSupport;?
@ParentPackage("default")?
@Results( { @Result(name = CRUDActionSupport.RELOAD, value = "/session", type = ServletActionRedirectResult.class) })?
public class SessionAction extends SimpleActionSupport {?
private static final String RELOAD = "reload";?
private static final long serialVersionUID = 8071034786218297672L;?
private String loginId;?
private SessionRegistry sessionRegistry;?
List<String> loginIds;?
?????????? //默认方法?
public String execute() throws Exception {?
?? return list();?
}?
?????????? //列表当前登录的用户的loginIds?
public String list() throws Exception {?
?? Object[] loginIds_obj = sessionRegistry.getAllPrincipals();?
?? if (loginIds_obj != null && loginIds_obj.length > 0) {?
??? loginIds = new ArrayList<String>(loginIds_obj.length);?
??? for (int i = 0; i < loginIds_obj.length; i++) {?
???? loginIds.add((String) loginIds_obj[i]);?
??? }?
?? }?
?? return SUCCESS;?
}?
//根据传入的loginId,踢出某用户?
public String destroy() throws Exception {?
?? SessionInformation[] sessions_arrs = sessionRegistry.getAllSessions(?
???? loginId, false);?
?? if (sessions_arrs != null && sessions_arrs.length > 0) {?
??? for (int i = 0; i < sessions_arrs.length; i++) {?
???? sessions_arrs[i].expireNow();?
???? // sessionRegistry.removeSessionInformation(sessions_arrs[i].getSessionId());?
??? }?
?? }?
?? return RELOAD;?
}?
public String getLoginId() {?
?? return loginId;?
}?
public void setLoginId(String loginId) {?
?? this.loginId = loginId;?
}?
public List<String> getLoginIds() {?
?? return loginIds;?
}?
public void setLoginIds(List<String> loginIds) {?
?? this.loginIds = loginIds;?
}?
public void setSessionRegistry(SessionRegistry sessionRegistry) {?
?? this.sessionRegistry = sessionRegistry;?
}?
}?

热点排行