欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

完整的redis保存用户信息,cookie保存sessionId实现登录流程

程序员文章站 2024-03-19 22:27:34
...



1. 完整的redis保存用户信息,cookie保存sessionId实现登录流程

登录流程

  1. cookid中存入sessionId并持久化到本地,把它的过期时间设置长一点
//1. 把登录信息存入cookie 中
CookieUtil.writeLoginToken(httpServletResponse,session.getId());
-----------------》writeLoginToken()方法
    /**
     * 存入cookie到本地
     */
    public static void writeLoginToken(HttpServletResponse response,String token){
        Cookie ck = new Cookie(COOKIE_NAME,token);
        //跨域共享,设置的值是B机器的域名,所以当B机器访问这个Cookie的时候是能访问到的
        ck.setDomain(COOKIE_DOMAIN);
        //代表设置在根目录
        ck.setPath("/");
        ck.setHttpOnly(true);
        //单位是秒。如果这个maxAge不设置的话,cookie就不会写入硬盘,而是写在内存。只在当前页面有效。
        //如果是-1,代表永久
        ck.setMaxAge(60 * 60 * 24 * 365);
        log.info("write cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
        response.addCookie(ck);
    }


  1. redis中存入用户信息(value),存入之前把用户信息转换成json格式,把sessionId作为key,并设置过期时间
//2. 把登录信息存入redis 中(response.getData()获得了查询出来的user对象)
RedisShardedPoolUtil.setEx(session.getId(), JsonUtil.obj2String(response.getData()),Const.RedisCacheExtime.REDIS_SESSION_EXTIME);

-----------------》setEx()/**
     * 存入一个值并设置过期时间
     */
    //exTime的单位是秒
    public static String setEx(String key,String value,int exTime){
        ShardedJedis jedis = null;
        String result = null;
        try {
            jedis = RedisShardedPool.getJedis();
            result = jedis.setex(key,exTime,value);
        } catch (Exception e) {
            log.error("setex key:{} value:{} error",key,value,e);
            RedisShardedPool.returnBrokenResource(jedis);
            return result;
        }
        RedisShardedPool.returnResource(jedis);
        return result;
    }








访问流程

  1. 添加一个过滤器,每次访问.do结尾的方法,都会经过过滤器并重置redis中存储用户信息的时间
--------------》过滤器主要方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;

        //1. 从cookie中获取value值(也就是session的值)
        String loginToken = CookieUtil.readLoginToken(httpServletRequest);
-----------》readLoginToken方法
/**
 * 获取存储的cookie
 */
public static String readLoginToken(HttpServletRequest request){
    Cookie[] cks = request.getCookies();
    if(cks != null){
        for(Cookie ck : cks){
            log.info("read cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
            if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
                log.info("return cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
                return ck.getValue();
            }
        }
    }
    return null;
}



        //2. 如果value不为空
        if(StringUtils.isNotEmpty(loginToken)){

            //2.1 通过session(也就是cookie的value和redis中的key)值获取用户信息
            String userJsonStr = RedisShardedPoolUtil.get(loginToken);
--------------get方法
/**
 * 通过key获取一个值
 */
public static String get(String key){
    ShardedJedis jedis = null;
    String result = null;
    try {
        jedis = RedisShardedPool.getJedis();
        result = jedis.get(key);
    } catch (Exception e) {
        log.error("get key:{} error",key,e);
        RedisShardedPool.returnBrokenResource(jedis);
        return result;
    }
    RedisShardedPool.returnResource(jedis);
    return result;
}


            User user = JsonUtil.string2Obj(userJsonStr,User.class);
--------------------》string2Obj方法
/**
 *将json格式转换成匹配的对象或者集合;(1)
 *
 * @param str 要转换的json字符串
 * @param clazz 要转换成的类型
 */
public static <T> T string2Obj(String str,Class<T> clazz){
    if(StringUtils.isEmpty(str) || clazz == null){
        return null;
    }

    try {
        return clazz.equals(String.class)? (T)str : objectMapper.readValue(str,clazz);
    } catch (Exception e) {
        log.warn("Parse String to Object error",e);
        return null;
    }
}


            //2.2如果成功获取值,重新设置一个redis中的过期时间(因为每次拿到的用户信息就是从reids中拿的)
            if(user != null){
                //如果user不为空,则重置session的时间,即调用expire命令
                RedisShardedPoolUtil.expire(loginToken, Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
--------------------------------》expire方法
/**
 * 设置key的有效期,单位是秒
 */
public static Long expire(String key,int exTime){
    ShardedJedis jedis = null;
    Long result = null;
    try {
        jedis = RedisShardedPool.getJedis();
        result = jedis.expire(key,exTime);
    } catch (Exception e) {
        log.error("expire key:{} error",key,e);
        RedisShardedPool.returnBrokenResource(jedis);
        return result;
    }
    RedisShardedPool.returnResource(jedis);
    return result;
}
      
            }
        }

        //3. 放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

  1. (访问了方法)获取redis中存入的登录信息
		//1. 获取redis中存入的登录信息
        String userJsonStr = RedisShardedPoolUtil.get(loginToken);
 -------------------get方法上面有
  1. 并转化成对象格式

        //2. 转换成user对象格式
        User user = JsonUtil.string2Obj(userJsonStr,User.class);
------------》string2Obj方法上面也有,注意这里只是一个类型转换








退出流程

  1. 删除cookie

        //1. 删除cookie
        CookieUtil.delLoginToken(httpServletRequest,httpServletResponse);
 --------------》delLoginToken方法
     /**
     * 删除本地cookie
     */
    public static void delLoginToken(HttpServletRequest request,HttpServletResponse response){
        Cookie[] cks = request.getCookies();
        if(cks != null){
            for(Cookie ck : cks){
                if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
                    ck.setDomain(COOKIE_DOMAIN);
                    ck.setPath("/");
                    ck.setMaxAge(0);//设置成0,代表删除此cookie。
                    log.info("del cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
                    response.addCookie(ck);
                    return;
                }
            }
        }
    }
  1. 删除redis

        //2. 删除redis
        RedisShardedPoolUtil.del(loginToken);
----------------》del方法
    /**
     * 删除一个值
     */
    public static Long del(String key){
        ShardedJedis jedis = null;
        Long result = null;
        try {
            jedis = RedisShardedPool.getJedis();
            result = jedis.del(key);
        } catch (Exception e) {
            log.error("del key:{} error",key,e);
            RedisShardedPool.returnBrokenResource(jedis);
            return result;
        }
        RedisShardedPool.returnResource(jedis);
        return result;
    }




注意

  1. 例如登录流程之类的,他们是同一个方法中的两个步骤,只截取了主要部分,下面特意把它们使用的方法都写出来了,都是自己写好的工具类
  2. 注意设置的setDomain属性,因为nginx有两台tomcat,所以要实现单点登录,所以我们就要保证域名是一级域名,a和b两台服务器都能访问到的那种,这样两个tomcat才可以访问同一个cookie
相关标签: cookie 单点登录