zoukankan      html  css  js  c++  java
  • 分布式session管理解决方案

    一、传统系统session管理方案

    1.利用cookie存放

    将Session对象保存在Cookie,然后存放在浏览器端。每次浏览器向服务器发送请求的时候,都会把整个Session对象放在请求里一起发送到服务器,以此来实现Session共享。这样的方案实现起来特别方便,但是由于Cookie的存储容量比较小,所以这个方案只适用于Session数据量小的场景。

    2.Session复制

    官方文档:Clustering/Session Replication How-To

    部分应用服务器能够支持Session复制功能,例如Tomcat。用户可以通过修改配置文件,让应用服务器进行Session复制,保持每一个服务节点的Session数据达到一致。但是这个方案的实现依赖于应用服务器。当应用被大量用户访问时,每个服务器都需要有一部分内存用来存放Session,同时因为大量Session通过网路传输进行复制,将会占用网络资源,还可能因为网络延迟导致程序异常。

    3.Session粘滞

    利用负载均衡器的分发能力,将同一浏览器上同一用户的请求,都定向发送到固定服务器上,让这个服务器处理该用户的所有请求,这样只要这个服务器上保存了用户Session,就能保证用户的状态一致性。但是这个方案依赖于负载均衡器,而且只适用于横向扩展的集群场景,不能满足分布式场景。

    二、分布式系统session集中管理方案

    分布式系统中,我们会将session集中存储,比如存储到redis中。这种方案比较常见的实现方式就是RedisSessionManager和Spring-Session。

    1.RedisSessionManager 

    官网:tomcat-redis-session-manager

    测试实验:使用tomcat-redis-session-manager实现session共享

    tomcat-redis-session-manager是一个基于Redis和Tomcat实现Session集中管理的开源方案。通过扩展Tomcat的SessionManager,并且在配置文件中替换Tomcat默认的SessionManager来实现Session管理。虽然实现起来比较简单,但是与Tomcat耦合,不适用于其他Web服务器。

    2.Spring-Session

    官方文档:Spring-Session

    Spring Session是Spring提供的一套Session管理方案,通过一个SessionFilter将所有访问应用的请求都拦截下来,然后使用Request包装类接管Session管理。SpringSession不与应用服务器耦合,能适用于常规服务器。同时还提供了在浏览器下对同一应用存储多个Session等功能。

    3.基于Spring-Session改造实现

    SpringSession优点颇多,所以开始的时候我们曾尝试将SpringSession集成到公司产品中来进行Session集中管理,但在集成过程中考虑到以下几点,最终放弃了集成。

    • SpringSession功能丰富,但我们并不是都需要。
    • SpringSession的实现代码量较多,还需要配合Spring-data-redis进行使用。
    • 如果后续要对Session管理的代码进行修改维护,需要把SpringSession的代码都梳理一遍,学习维护成本比较高。

    所以最终我们决定使用Redis作为Session的存储介质,然后参考SpringSession的实现理念,自己设计开发一套轻量级的Session集中管理实现。

    同样使用SessionFilter进行用户请求拦截,然后通过Request包装类接管应用服务器的Session管理。在Request包装类中重写getSession方法。让用户在进行Session读写的时候去Redis中进行操作,而且使用Session的方法与过去一样,使得管理方案对用户透明。

    在Session共享模块与Redis之间,基于jedis开发了一个分布式缓存SDK,用于进行通信,同时SDK可以提供扩展性,后续如果需要支持其他的缓存服务器,只要对SDK进行扩展开发即可。

    然后为了保证Session集中管理方案的高可用,将会搭建Redis集群来存储Session对象。下面是一个推荐客户搭建的最小Redis集群,集群中共有4个Redis节点,两主两从。两个Master节点用来对Session数据进行分片存储,而Slaver节点用来对Matser进行数据备份和读写分离。

    三、微服务系统告别session,引入jwt

    在微服务中抛弃session

    在微服务体系架构中,微服务应用是由多个相互独立的微服务进程组成的,对每个微服务的访问都需要进行用户认证。微服务应用应遵循单一职责原理,即一个微服务只处理单一的业务逻辑。认证和鉴权的公共逻辑不应该放到微服务实现中。因此需要考虑一个抽象、公共的逻辑,统一对用户进行身份认证和鉴权服务。

    (简而言之:Redis集中存储与微服务的理念相冲突。但实际上在微服务中继续使用Redis集中存储方案也是可行的,只是一般不会这么干!)

    下面的问答也说明了这个问题,来源于多个微服务之间的session共享问题

    问题:
    现在我们有一个zuul+redis+springcloud,然后有多个springboot做的微服务,其中有一个专门做个人中心的微服务,我们会在这个服务做注册登录操作,然后别的微服务做业务处理。
    因为是第一次做,不知道这个网关究竟可不可以做到多个微服务之间的session共享,就是我们在微服务A做了登录操作,保存用户信息到session,然后在微服务B里面取到用户信息。
    多个微服务的项目名是不一样的。如果是同一个微服务,部署在不同的服务器上面这种情况我们是可以做到session共享。
    
    某个回答:
    不建议系统设计成这样子
    微服务连数据库都是隔离的,你这连缓存都能共享,这个不合理,各个服务都能访问session,如果个人中心升级,session存储的对象结构变化其他服务是不是都得升级?
    服务倒是可以有办法多个版本兼容,但你session只有一个,你这耦合度太高,有违微服务架构的初衷。
    建议做成松散的授权登录模式比较好 

    解决方案

    1.用户身份的认证:

    由于在微服务架构中以API Gateway作为对外提供服务的入口,因此可以考虑在API Gateway处提供统一的用户认证。具体技术实现可以采用Zuul+Spring Security+OAuth2/JWT。

    2.用户状态的保持:

    在单体应用时,我们是在服务器端采用Session和客户端采用Cookie来保存用户状态,由于在服务器是有状态的,对服务器的水平扩展有影响。而微服务架构的优势之一就是微服务的水平扩展和弹性,所以微服务最好是无状态的,因此建议采用Token来记录用户登录状态。token会存储在客户端中,其工作流程与session/cookie那一套实际上是类似。

    3.用户注销:

    由于Token存储在客户端而非服务端,当用户注销时,Token的有效时间还没有到,还是有效的。所以如何在用户注销登录时让Token注销是一个要关注的点。一般有如下几种方式:

    Token存储在Cookie中,这样客户端注销时,自然可以清空掉

    将Token存放到分布式缓存中,每次校验Token时区检查下该Token是否已注销。不过这样也就失去了快速校验Token的优点。(不推荐)

    多采用短期令牌,比如令牌有效期是30分钟,这样可以一定程度上降低注销后 Token可用性的风险。

    4.用户的权限控制:

    API Gateway处进行统一的权限控制
    客户端发送的HTTP请求中包含有请求的Resource及HTTP Method。如果系统遵循REST规范,以URI资源方式对访问对象进行建模,则API Gateway可以从请求中直接截取到访问的资源及需要进行的操作,然后调用Security Service进行权限判断,根据判断结果决定用户是否有权限对该资源进行操作,并转发到后端的Business Service。这种实现方式API Gateway会统一处理认证和鉴权逻辑,各个微服务不需要考虑用户认证和鉴权,只需要处理业务逻辑,简化了各微服务的实现。

    5.服务间的认证:

    微服务应用,除了来自用户和第三方的访问外,还有大量的微服务之间访问。根据微服务应用的数据敏感程度的不同,对于微服务之间的相互访问可能有不同的安全要求

    • 微服务间的相互访问不进行认证和鉴权
      1.依托网络安全措施,来保障微服务间的通讯安全
      2.微服务提供的数据敏感程度不是很高。
      在这种情况下,一旦攻击者侵入到内部网络后没有了保护措施。虽然微服务的数据敏感程度不高,但攻击行为仍给我们带来危害。
    • 微服务间的相互访问采用颁发访问凭证进行安全控制
      微服务在使用的维度上,我们定义服务的调用方和服务的提供方。服务的提供方对调用方颁发访问凭证,提供方对访问严格控制;
      没有访问凭证的访问,拒绝访问;根据不同的访问凭证类型,安全控制不同的访问类型。
    • 微服务间的相互访问采用Service Account进行安全控制
      Istio-Auth提供强大的服务间认证和终端用户认证,使用交互TLS,内置身份和证书管理。可以升级服务网格中的未加密流量,并为运维人员提供基于服务身份而不是网络控制来执行策略的能力。Istio的未来版本将增加细粒度的访问控制和审计,以使用各种访问控制机制(包括基于属性和角色的访问控制以及授权钩子)来控制和监视访问您的服务,API或资源的人员。
      Istio官网:https://istio.io/docs/concepts/security/

    jwt官网:https://jwt.io/

    Oauth官网:https://www.oauth.com

    CAS官网:https://www.apereo.org/projects/cas

    参考:

    如何构建安全的微服务应用

    微服务统一登陆认证怎么做?JWT ?

    Spring Cloud下微服务权限方案(老A)

    不积跬步,无以至千里。不积小流,无以成江海!
  • 相关阅读:
    wordpress 的主题
    yapi api协作管理平台
    美团外卖券小程序路径过长导致插入文本消息失败的问题解决办法
    mp://XzDiXafjfvLnjvp
    supervisor 命令
    YII beego gin 框架对比
    芝麻微客-企业微信公域到私域流量运营助手
    H5跳转小程序
    PowerBI开发 第十九篇:基于Page创建Tooltip
    PowerBI开发 第十八篇:行级安全(RLS)
  • 原文地址:https://www.cnblogs.com/rouqinglangzi/p/10703610.html
Copyright © 2011-2022 走看看