利用Redis实现限制一个用户只能在一个地点登陆
来源:互联网 发布:caffe linux cpu 安装 编辑:程序博客网 时间:2024/06/06 12:22
由于业务需要,需要实现一个用户在本系统内只能在一个地点登录,如果在多个地点登录,需要将之前的登录废弃掉,不能正常请求服务器数据。
大体是这样实现的:每次请求接口数据(除过登录接口之外)需要验证SessionId,验证SessionId步骤:
1.先从request中获取requestedSessionId,如果不是空(串),然后去redis中获取该sessionId对应的UserId(用户唯一标识),走第二步;如果是空,需要登录
2.然后再通过userId获取缓存了的sessionId,如果缓存的sessionId不是空,走第三步;是空,需要登录
3.对比缓存的sessionId和从request中获取requestedSessionId是否一致,不一致则说明在别处登录,一致正常响应即可。
详细代码如下:
拦截器部分:
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.StringUtils;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * Created by Administrator on 2016/9/24. */public class SessionControlInterceptor extends HandlerInterceptorAdapter { @Autowired private JedisPool jedisPool; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestedSessionId = request.getRequestedSessionId(); String userId = null; Jedis jedis = null; try { jedis = jedisPool.getResource(); if (!StringUtils.isEmpty(requestedSessionId)) { userId = jedis.hget("sessionHash", requestedSessionId); } if (StringUtils.isEmpty(userId)) { response.getWriter().write("{\"message\":\"请先登陆\"}"); return false; } else { String cacheSessionId = null; String sessionKey = userId + "-onlyLogin"; try { cacheSessionId = jedis.get(sessionKey); } catch (Exception e) { e.printStackTrace(); } if (StringUtils.isEmpty(cacheSessionId)) { response.getWriter().write("{\"message\":\"请先登陆\"}"); return false; } else { if (!cacheSessionId.equals(requestedSessionId)) { response.getWriter().write("{\"message\":\"您的账号已在别处登陆,请重新登陆\"}"); return false; } else { jedis.expire(sessionKey, 30 * 60); return super.preHandle(request, response, handler); } } } } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { jedis.close(); } } response.getWriter().write("{\"message\":\"服务器忙\"}"); return false; }}
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;/** * * @author Administrator * 2016年7月9日 上午10:42:05 * */@Configurationpublic class WebAppConfig extends WebMvcConfigurerAdapter { @Bean SessionControlInterceptor sessionControlInterceptor(){ return new SessionControlInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CrossDomainInterceptor()).addPathPatterns("/**"); registry.addInterceptor(sessionControlInterceptor()).excludePathPatterns("/**/login/**"); super.addInterceptors(registry); }}
登录时设置Sesssion部分
private void setSessionInfo(String userId, HttpServletRequest request) { HttpSession session = request.getSession(); String sessionId = session.getId(); session.setAttribute("userId", userId); Jedis jedis = null; try {String key = userId + "-onlyLogin"; jedis = jedisPool.getResource(); jedis.set(key , sessionId);jedis.expire(key,30 * 60);jedis.hset("sessionHash", sessionId, userId); } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { jedis.close(); } }}
还有就是要定期清理sessionHash中不用了的sessionId,这个需要获取所有匹配表达式 *-onlyLogin 的值,与sessionHash的fields对比,找出未使用的,进行删除清理。否则这个sessionHash可能会超级大。
0 0
- 利用Redis实现限制一个用户只能在一个地点登陆
- redis实现session共享,解决一个账号只能在一个终端登陆
- 限制一个账号同时只能在一处登陆
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- 一个用户只能在一部机里登陆一次
- java实现统一账户同一时间只能在一个地方登陆
- 【oracle】限制用户只能建立一个会话
- 限制同一时间只能一个用户登录
- 如何控制一个用户只能一个人登陆
- 关于在cocos2d-x中一个精灵移动到 另外一个地点的实现方法。
- Springmvc在限制只能在一处登陆
- app限制一个账号只能单设备登陆
- 利用spring security控制同一个用户只能一次登陆
- iOS中的颜色
- 将PHP C++扩展从php5升级到php7
- Android Studio官方文档:如何构建简单的用户界面
- PkgUtils(用于获取版本名称和版本号)
- 打印LLVM::Type或者LLVM::Value的值
- 利用Redis实现限制一个用户只能在一个地点登陆
- Aerospike数据库实战(二) -- 哪种SSD产品更适合Aerospike (Intel DC s3500 SSD VS Fusion ioDrive PCIe )
- C程序设计语言- 结构-5.1----结构的基本知识、结构与函数、结构数组、指向结构的指针
- Android之TelephonyManager类的方法详解
- Linux 格式化分区 报错Could not stat --- No such file or directory 和 partprobe 命令
- Mybatis常见问题
- 从一个复数点积算法看NEON的汇编优化(NEON优化实例)
- 数据库连接池的实现及分析
- spring与mybatis集成的几种方式