利用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
原创粉丝点击