Apache shiro如何实现一个账户同一时间只能在一个浏览器登录

会话

即用户访问应用时保持的连接关系,通过会话应用可以在多次访问中识别出当前的用户是谁,还可以在交互中保存数据。

限制登录功能,用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的对象
DategetLastAccessTime() 获取最后的访问时间
Date    getStartTimestamp()获取session的启动时间

我这里用到了就是getLastAccessTime()这个获取最后访问时间的方法,
判断当前时间距离最后一次访问时间 :
如果大于5分钟 说明前者登录有5分钟以上未操作页面,清除此session以后,后者就可以进行登录;
如果小于5分钟 说明前者5分钟内有操作过页面,提示后者可以先进行退出再登陆,或者等几分钟再登陆;
 

//移除5分钟内无操作的会话 目的就是 防止用户非正常退出,直接关闭浏览器或断电,session未过期或未清除
sessionDao.delete(session);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值