会话
即用户访问应用时保持的连接关系,通过会话应用可以在多次访问中识别出当前的用户是谁,还可以在交互中保存数据。
限制登录功能,用shiro安全框架管理session会话
效果就是 不让同一个账户通过其他浏览器进行二次登录,除非在已登陆页面超过5分钟未进行任何操作,才可以再次登录
话不多说上代码
//Controller层如下:
@Resource private SessionDAO sessionDao;
@ResponseBody
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponsePojo login(String username, String password, String captcha)throws IOException {
//验证码校验省略。。。
//用户名密码非空校验省略。。。
try{
Subject subject = ShiroUtils.getSubject();
//获取当前已登录的用户session列表
Collection<Session> sessions = sessionDao.getActiveSessions();
for (Session session : sessions) {
Subject s = new Subject.Builder().session(session).buildSubject();
//判断是否已通过认证
if (s.isAuthenticated()) {
SysUser u = (SysUser) s.getPrincipal();
//sessionId不同 且 登录用户名相同——>进行登录限制
if (u!=null && username.equalsIgnoreCase(u.getUsername()) &&
!session.getId().equals(subject.getSession().getId())) {
//获取目前未操作时长
long timeOut = (new Date().getTime() - session.getLastAccessTime().getTime());
if (timeOut>300000){
//移除5分钟内无操作的会话
sessionDao.delete(session);
}else {
return ResponsePojo.error("账号已登录,请先从其他平台退出登录;或者请"+
((300000 - timeOut)/60000+1)+"分钟后重试");
}
}
}
}
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//登录认证
subject.login(token);
}catch (Exception e) {
//其他异常省略。。。
msg = e.getMessage();
return ResponsePojo.error(msg);
}
}
shiro-会话管理:
shiro自己实现了一套session管理体系可以在不借助任何web容器或servlet的情况下使用session。
SessionManager(session管理器)、SessionDAO(实现session的增删改查)
所以还要配置shiro.xml
<!-- 实现session的增删改查 -->
<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
</bean>
<!-- session管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- 设置session过期时间为12小时(单位:毫秒),默认为30分钟 -->
<property name="globalSessionTimeout" value="43200000"></property>
<property name="sessionValidationSchedulerEnabled" value="true"></property>
<property name="sessionDAO" ref="sessionDAO"/>
</bean>
shiro-会话相关API:
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
拿到session之后,就可以调用以下API(省略一部分。。。)
返回值 | 方法名 | 描述 |
---|---|---|
Serializable | getId() | 获取session的唯一id |
Object | getAttribute(Object key) | 根据key标识返回绑定到session的对象 |
Date | getLastAccessTime() | 获取最后的访问时间 |
Date | getStartTimestamp() | 获取session的启动时间 |
我这里用到了就是getLastAccessTime()这个获取最后访问时间的方法,
判断当前时间距离最后一次访问时间 :
如果大于5分钟 说明前者登录有5分钟以上未操作页面,清除此session以后,后者就可以进行登录;
如果小于5分钟 说明前者5分钟内有操作过页面,提示后者可以先进行退出再登陆,或者等几分钟再登陆;
//移除5分钟内无操作的会话 目的就是 防止用户非正常退出,直接关闭浏览器或断电,session未过期或未清除
sessionDao.delete(session);
不足之处请指出
转发引用请注明原文地址