今天我们记录一下shiro的一个账号安全。
在网上看了一下其他人的实现,个别案例显得繁琐,配置太过于沉重,今天在这里介绍一种简单的方法。
1.首先说一下我实现的思路
- 首先,在这之前我们知道,当用户登陆成功之后,shiro会将用户的一些信息存储的sessionDao,同时,对于同一个浏览器对不同的账号,登陆时产生相同的sessionId,这也导致了用户信息之间的覆盖,不同的浏览器对于不同的账号,会产生不同的sessionId,(网上有一些根据sessionId来实现的我是没有看懂)
- 既然我们知道shiro会将用户存储到sessionDao 那么,我们就可以从shiro中拿出这些登陆的信息,然后作比较,根据id或者name随意啦,如果匹配上了,那么我们就将这个session强制下线,添加我们新的session,那么我们的功能就实现了。
2.xml配置(我只提供最简单的配置,如果没有特殊的要求是够用了)
根据上面的思路,我们总结一下,我们需要用到的有sessionDao,sessionManage(session的管理器当然需要拉),就OK了,当 然shiro框架的整合配置就不说了,肯定要配置啊。
- 1.加载我们的sessionDao
<bean id="sessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"/>2.加载我们的sessionManage,她需要依赖我们的sessionDao
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDao"/>
</bean>- 3.在sessionmanag
- e加载到securityManage中,
<!-- securityManager安全管理器 -->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="customRealm"></property>
<!-- 注入缓存管理器 -->
<property name="cacheManager" ref="cacheManager"></property>
<property name="sessionManager" ref="sessionManager"></property>
</bean>到这了xml的配置就ok了
3.修改我们的认证方法
@Autowired
private SessionDAO sessionDAO;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken aToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken)aToken;
String username = token.getUsername();
//判断用户名是否存在
User user = userService.selectUser(username);
//声明一个user用来获取sessionDao中的user
User userSession = null;
if(user != null){
//获取在线的session
Collection<Session> sessionCollection = sessionDAO.getActiveSessions();
for (Session session : sessionCollection){
//session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); 获取simpleAuthenticationInfo的第一个参数的值
if(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) != null) {
//根据session build出一个subject
Subject subject = new Subject.Builder().session(session).buildSubject();
//拿到这个登陆的对象
userSession = (User) subject.getPrincipal();
//判断她的code和我现在登陆的code是否一致 (code是我在数据库里面设置一个标识码 采用uuid 保证唯一性 这里你可以id)
if (user.getCode().equals(userSession.getCode())) {
//两者一致的时候,设置这个session的失效时间 (0:立刻)
session.setTimeout(0);
break;
}
}
}
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return authenticationInfo;
} else{
throw new AuthenticationException("用户名错误!");
}
}是不是和我们最初写的认证方法没什么区别,就多了一个foreach中的循环,注入了一个sessionDao,(就是我们在springbean.xml声明的那个sessionDao,)
到现在,你的账号就只能同时存在一台设备上了。喜欢就评论一下吧!
版权声明:本文为qq_39069111原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。