SpringMVC学习笔记3_通过redis缓存和cookie实现Session共享

摘要:

通过redis缓存和cookie实现单点登录


整体实现思路如下图所示。

SpringMVC学习笔记3_通过redis缓存和cookie实现Session共享_第1张图片


1.业务系统发起登录请求,调用SSO用户登录接口;


2.SSO登录接口的处理逻辑:

2.1 根据用户名和密码去数据库验证用户是否合法。

2.2 用户验证通过之后,生成SessionID,并返回给业务系统。

   同时以SessionID为key,存储用户信息到redis缓存中


  SSO登录接口代码:
  public JSONObject userLogin(@RequestBody JSONObject jsonObject){
        UserLoginResponse userLoginResponss = new UserLoginResponse();
        try {
            logger.info("处理用户登录业务逻辑,接收报文"+jsonObject);
            String msgWithDigesta=SecurityUtil.scfMatch(jsonObject.toString(), newXService.getPrivateKey());
            //生成实体
            User user = JSONObject.parseObject(msgWithDigesta,User.class);
            //是否验证用户的密码
            boolean isChechPassword = true;
            User userInfo = anaService.loginCheckUserInfo(user,isChechPassword);
            // 存储用户信息到redis缓存中
            String ticket = anaService.storeUserLoginSessionInRedis(userInfo,user.getModuleCode());
            userLoginResponss.setRetCode(RetCode.LOGIN_SUCCESS.getCode());
            userLoginResponss.setRetMessage("用户登录成功");
            userLoginResponss.setTicket(ticket);
            userLoginResponss.setStatus(userInfo.getStatus());
            userLoginResponss.setIsModifyPassword(userInfo.getIsModifyPassword());
        } catch (Exception e) {
            userLoginResponss.setRetCode(RetCode.LOGIN_FAILED.getCode());
            userLoginResponss.setRetMessage(e.getMessage());
            logger.info("插入用户数据到表中失败,原因:"+e.getMessage());
        }
        logger.info("返回处理用户登录业务逻辑结果,Result{[]}"+JSONObject.toJSONString(userLoginResponss));
        return JSON.parseObject(JSONObject.toJSONString(userLoginResponss));
    }


存储用户信息到redis缓存的代码:

  /**
     * 存储用户登录session信息到redis中
     * @param userInfo
     * @return
     */
    public String storeUserLoginSessionInRedis(User userInfo,String moduleCode) {
        // 存储用户ticket信息
        // 使用AES加密登录用户ID生成SessionID,加密密码是配置文件里定义的64位字符串
        String sessionId = AesUtil.encrypt(String.valueOf(userInfo.getUserId()), newXService.getBizkey());
        String unique_ticket = userInfo.getSystemId()+sessionId+"_USER_LOGIN";
        //
        String ticket = userInfo.getSystemId()+sessionId+System.currentTimeMillis()+"_USER_LOGIN";

        UserLoginSession userLoginSession = new UserLoginSession();
        userLoginSession.setUserId(String.valueOf(userInfo.getUserId()));
        userLoginSession.setUserName(userInfo.getUserName());
        userLoginSession.setUserLoginName(userInfo.getUserLoginName());
        // 获取权限
        List permissions = getUserPermissions(userInfo.getUserId());
        userLoginSession.setPermissions(permissions);
        
        userLoginSession.setModuleCode(StringUtils.killNull(userInfo.getModuleCode()));
        userLoginSession.setLastLoginTime(userInfo.getLastLoginTime());
        userLoginSession.seteId(StringUtils.killNull(userInfo.geteId()));
        userLoginSession.setSessionId(ticket);
        userLoginSession.setUserInfo(userInfo);    

        //限制唯一登录,删除上一个用户信息
        if (redisService.exists(unique_ticket))
            redisService.del(redisService.get(unique_ticket));

        redisService.set(unique_ticket, ticket);

        logger.info("访问AnaController的login方法:放进redis"+ticket);
        redisService.setKeyExpire((ticket).getBytes(),1800);

        logger.info("userloginsession result ="+JSONObject.toJSONString(userLoginSession));
        return ticket;
    }


 

3.业务系统将返回的sessionID,存放到cookie里


  业务系统controller的代码:
 @RequestMapping("/login.ajax")
    public
    @ResponseBody
    Map login(@RequestParam("username2") String username2,
                              @RequestParam("moduleCode2") String moduleCode2,
                              @RequestParam("password2") String password2, String requestUrl, HttpServletResponse response) {
            // 其他业务逻辑省略
            String sessionId = userBySso.getTicket();
            Cookie cookie = new Cookie("CORE_SESSION", sessionId);
            cookie.setPath("/");
            response.addCookie(cookie);
            // 其他业务逻辑省略
}


4.业务系统取得Session信息,并检验用户信息

业务系统的页面发起web请求时,

在自定义拦截器(继承自HandlerInterceptor)的preHandle方法里取得session信息,
并检查用户是否登录。
Session信息取得时,首先从cookie中取得SessionId,然后根据SessionId从redis取得用户信息

自定义拦截器的代码此处省略,请参照 【SpringMVC学习笔记2_拦截器实现登录验证】,以下是取得session信息的代码

  public UserLoginSession getUserLoginSession(HttpServletRequest req) {
        logger.info("访问getUserLoginSession");

        String sessionId = "";
        Cookie[] cookie = req.getCookies();
        if (cookie == null) {
            return null;
        }
        for (int i = 0; i < cookie.length; i++) {
            Cookie cook = cookie[i];
            if (cook.getName().equals("CORE_SESSION")) {
                sessionId = cook.getValue().toString();
            }
        }

        logger.info("访问getUserLoginSession获取sessionId: " + sessionId);

        if ("".equals(sessionId)) {

            return null;
        }

        String UserLoginSessionStr = redisService.get(sessionId);

        logger.info("访问getUserLoginSession获取USERLOGINSESSION: " + UserLoginSessionStr);

        if (null == UserLoginSessionStr || "".equals(UserLoginSessionStr)) {

            return null;
        }

        UserLoginSession userLoginSession = (UserLoginSession) JSONObject.toJavaObject(JSONObject.parseObject(UserLoginSessionStr), UserLoginSession.class);
        logger.info("访问getUserLoginSession获取USER_ID成功: " + userLoginSession.getUserId());
        redisService.setKeyExpire((sessionId).getBytes(), 1800);
        redisService.setKeyExpire((userLoginSession.getTicketRole()).getBytes(),1800);
        return userLoginSession;
    }



你可能感兴趣的:(SpringMVC)