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个方法。

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值