分布式项目中要实现单点登录(SSO - Single Sign On):对于同一个客户端(例如 Chrome 浏览器),只要登录了一个子站(例如 a.com),则所有子站(b.com、c.com)都认为已经登录。 
比如用户在登录淘宝后,跳转到天猫时就已经登录了。

用例步骤

未登录用户访问子站 a.com 进行登录,自动跳转到账户中心的统一登录页 account.com/login
用户在统一登录页进行登录,登录成功后显示登录跳转页
显示登录跳转页后自动跳转回 a.com,单点登录完成
用户在访问 b.com 时无需再次登录

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

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

Session的缓存机制

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<Permission> 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")  @ResponseBody  public  Map<String, Object> 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学习笔记2_拦截器实现登录验证】,以下是取得session信息的代码
---------------------
作者:hchhan
来源:CSDN
原文:https://blog.csdn.net/hchhan/article/details/78390280
版权声明:本文为博主原创文章,转载请附上博文链接!

参考:

https://blog.csdn.net/hchhan/article/details/78390280

转载于:https://www.cnblogs.com/xiaohuizhenyoucai/p/11051826.html

redis缓存和cookie实现Session共享相关推荐

  1. php 集群 session共享,Session共享:php和redis集群如何实现Session共享

    本篇文章给大家带来的内容是关于Session共享:php和redis集群如何实现Session共享,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一.redis 数据库集群安装软件版 ...

  2. tomcat+nginx+redis实现均衡负载、session共享(一)

    在项目运营时,我们都会遇到一个问题,项目需要更新时,我们可能需先暂时关闭下服务器来更新.但这可能会出现一些状况: 1.用户还在操作,被强迫终止了(我们可以看日志等没人操作的时候更新,但总可能会有万一) ...

  3. tomcat+nginx+redis实现均衡负载、session共享

    在项目运营时,我们都会遇到一个问题,项目需要更新时,我们可能需先暂时关闭下服务器来更新.但这可能会出现一些状况: 1.用户还在操作,被强迫终止了(我们可以看日志等没人操作的时候更新,但总可能会有万一) ...

  4. java分布式会话redis_详解springboot中redis的使用和分布式session共享问题

    对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomca ...

  5. 基于nginx tomcat redis分布式web应用的session共享配置

    一.前言 nginx 作为目前最流行的开源反向代理HTTP Server,用于实现资源缓存.web server负载均衡等功能,由于其轻量级.高性能.高可靠等特点在互联网项目中有着非常普遍的应用,相关 ...

  6. nginx + tomcat + redis 部署项目,解决session共享问题。

    最近自己搭了一套nginx的环境,集群部署了公司的一个项目,中间解决了session共享的问题.记录如下,以备日后查看. 1.环境 windows10 家庭中文版,jdk 7, tomcat 7.0. ...

  7. 使用 Nginx+SpringBoot+Redis 实现负载均衡以及session共享

    一.所需的环境 Redis 存储Session信息 两个Spring Boot 应用,均将session信息托管到上面的Redis Nginx 配置负载均衡策略 反向代理到SpringBoot应用 二 ...

  8. Tomcat通过Redis实现session共享的完整部署记录

    对于生产环境有了一定规模的tomcat集群业务来说,要实现session会话共享,比较稳妥的方式就是使用数据库持久化session.为什么要持久化session(共享session)呢?因为在客户端每 ...

  9. Tomcat集群通过redis实现session共享

    Tomcat集群通过redis实现session共享 最近在XXX项目上做了tomcat集群的session共享,闲来无事鄙人将整个踩坑的过程粗糙的记录下来,给同学们分享一波,整个过程无硬编码,爽歪歪 ...

最新文章

  1. Android中Activity的启动流程和组织管理方式(Backstack、Task)
  2. python基础——递归函数
  3. Can't connect to MySQL server on 'localhost' (1...
  4. [html] 如何去除标签<i>默认斜体?
  5. python运维开发之第八天(socket)
  6. python三方库之BeautifuSoup
  7. multism中ui和uo应该怎么表示_吐血整理!这篇带你彻底理解主存中存储单元地址的分配...
  8. Activity中四大启动模式
  9. Android HandlerThread 消息循环机制之源代码解析
  10. qt在linux下编译资源文件,linux下Qt qrc文件的编写与应用
  11. Python pyqt5绘画界面(文章可能啰嗦,不喜勿喷)
  12. 怎么在图片上直接编辑文字?建议收藏这些编辑方法
  13. 扫码签到之动态刷新二维码——给每一帧附加有效期(原理、web 小程序变量共享)
  14. library sort(图书馆排序)
  15. 领航云计算发展风向标,亚马逊云科技的这些硬核布局值得关注
  16. 教你在python中用不同的方式画不同颜色的画布
  17. [java]已知文件 source.txt 中的内容如下,其中,username、yonghu 都表示用户名,password、mima都表示密码,level、dengji都表示等级
  18. 将GIF转成视频MP4、MOV
  19. 变量、存储过程与函数
  20. HTML5 新增input属性

热门文章

  1. Java垃圾回收之老年代垃圾收集器
  2. 知名高校共享课程资源GitHub地址
  3. 关于素数的简单算法整理
  4. 深度学习的分布式训练--数据并行和模型并行
  5. 独家 | TensorFlow 2.0将把Eager Execution变为默认执行模式,你该转向动态计算图了...
  6. Python字节码介绍
  7. LeetCode简单题之删除一个元素使数组严格递增
  8. LeetCode简单题之独一无二的出现次数
  9. LeetCode简单题之检查整数及其两倍数是否存在
  10. 分布式,集中式,云原生存储技术