`
yangzhiyong77
  • 浏览: 964120 次
文章分类
社区版块
存档分类
最新评论

spring security3.0控制多个用户账号同时登录和管理员踢出用户(原创)

 
阅读更多

声明一下,这篇文章不是基于acegi spring security2.0写的, 我发现很多文章都是基于老版本写的, 并不适用最新版。

下面跟大家分享一下在spring security3.0里如何正宗的做法达到控制多个账号请求的经验。

步骤1

下面只贴出关键部分, 为了不影响阅读。

注意: 不需要配置 SessionRegistry 等bean( 假设你其他地方不用到的话, 如果用到需要在

<concurrency-control session-registry-ref="sessionRegistry" error-if-maximum-exceeded="true" max-sessions="1" />

加上一个属性

在做某个管理员踢出一个账号的时候, SessionRegistry 这个bean是需要用到的。 写法如下:

有时候按文档和网上配置出来是很华丽, 可事实有时候就是没有如期运行。

我打开火狐 360浏览器, 还是等两个账号同时登录。

无奈之下把源码下下载剖析(常干的事儿, 喜欢捣腾这些东西)

判断重复的类是ConcurrentSessionControlStrategy.java下的

checkAuthenticationAllowed这个函数的

最重要的一句话是:

sessionInformationList.get(j).expireNow();
这句强制T出了用户, (设置为过期)

如果想彻底删除, 加上

sessionRegistry.removeSessionInformation(sessionInformationList.get(j).getSessionId());

即可,

这样使用getAllPrincipals 则获取不到被T出的用户了, 其实原理不是直接删除User对象, 只结束了它的sessionId,

因为这个User可能不止对应着1个sessionId

我发现, 无论我怎么配置, sessionCount老是烦人的 0。 即使我手动配置了ConcurrentSessionControlStrategy这个bean也没用(默认会自己调的)

无奈中想自己写一个自定义的计数器控制, 但细想它这东西不至于这个小问题都出这么大的漏洞吧?

现在的问题是:

如何让 int sessionCount = sessions.size(); 这句在第二个账号登陆的时候不为0。

于是我进入了sessionRegistry.getAllSessions(authentication.getPrincipal(), false); 这个函数。

也就是SessionRegistryImpl.java

public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
final Set<String> sessionsUsedByPrincipal = principals.get(principal);

这个函数是通过在一个HashMap里拿到key value的。

而principals的声明这样写。

private final Map<Object,Set<String>> principals = Collections.synchronizedMap(new HashMap<Object,Set<String>>());

现在的问题变为了:

如何让两个principal, 也就是User, 也就是

public UserDetails loadUserByUsername(String username)

两次登陆的时候返回的是同一个对象。

那么如何做到两次在不同浏览器登陆的时候返回的是同一个User?

答案是java的基础, equal hashcode方法重写。

在User对象里添加以下方法:

涉及这方面的基础请参考 http://blog.csdn.net/willielee/archive/2010/08/11/5804463.aspx

我就不浪费CSDN的硬盘空间了, 不过还是得贴出最后一句话:

HashMap的key判断key是否相等也是从hashcode和equals是否相等判断

从上面可以看出, 我们之前登陆的用户是存在 Map<Object,Set<String>> principals 的。

这个存储结构是, 一个User 对应多个Set集合的sessionId。

所以要判断用户是否已存在登陆的了, 当然要重写这2个方法。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics