单体应用到分布式再到微服务,用户认证和授权机制的演进史
mhr18 2025-06-08 22:42 1 浏览 0 评论
Web应用和用户的身份验证息息相关,从单一服务器架构到分布式服务架构再到微服务架构,用户安全认证和授权的机制也一直在演进,下文对各个架构下的认证机制做个总结。
单一服务器架构
该架构下后端只有一台服务器提供服务。
- 认证授权流程:
1.Web应用中设置拦截器对所有请求进行拦截,如果校验不通过则跳转登陆重新认证
2.客户端发起认证请求,传入用户名密码
3.通过验证后,应用在服务器上将用户信息存入session中,并将session id返回给客户端
4.客户端将session id存在本地cookie或local storage中,再次访问时传入session id
5.Web应用根据session id对比服务器的session数据,确认用户身份
- 适合场景
这种模式只适合单服务器的场景
- 常用实现
shiro ;自定义注解 + 拦截器/AOP方案;filter方案等
- 缺陷
如果是分布式服务或跨域体系架构的系统则会出现session无法共享的问题。
- 如何解决
解决方案有两种,第一种是将session统一存放,实现分布式session共享,第二种方案是客户端生成token
分布式服务架构
分布式服务架构下,后端的服务器由一台变成了多台。
Session共享方案
- 认证授权流程:
1.使用nginx做负载均衡,多台web应用
2.客户端发起认证请求,根据策略到其中一台web
3.通过验证后,服务端将用户的信息存入持久化层,例如redis缓存数据库,再生成token令牌
4.并将生成的token返回客户端,存入客户端缓存。
5.客户端再次访问web,根据策略路由到其中一台,web应用查询持久化层,根据带入的token查询用户登陆信息,确认身份。
- 适合场景
并发量不高的分布式应用
- 常用实现
shiro ;自定义注解 + 拦截器/AOP方案;filter方案等
- 缺陷
1、这种方案的缺陷在于依赖于持久层的数据库如redis,会有单点风险,如果持久层失败,整个认证体系都会挂掉;
2、每一次调用都需要访问持久化层进行验证,会给持久化层造成压力,在高并发场景,持久化层容易成为瓶颈;
- 如何解决
持久层的数据库如redis做高可用和集群。
客户端token方案
- 认证授权流程:
1.客户端发起认证请求,根据策略到其中一台web
2.通过验证后,服务端将用户登陆信息封装成token(token本身可以自解释)返回给客户端,不存储在服务端
3.客户端将返回的完整信息存入缓存。
4.客户端再次访问web,根据策略路由到其中一台,带入登陆信息,服务端根据信息确认身份。
- 适合场景
优势在于服务端不保存用户会话数据,服务端无状态,不用去持久层查询从而增加了效率,适合一次性验证、restful api 的无状态认证、并发量较高的分布式应用等
- 常用实现
jwt
- 缺陷
token一旦下发便不受服务端控制,如果发生token泄露,服务器也只能任其蹂躏,在其未过期期间不能有任何措施,同时存在以下两个问题:
1、失效问题,因为token是存放在客户端的,服务端无法主动让token失效,比如踢人下线、用户权限发生变化等场景就实现不了
2、续签问题,token 有效期一般都建议设置的不太长, token 过期后用户需要重新登录,导致用户需要频繁登录
- 如何解决
针对失效问题:
① 将 token 存入内存数据库:将 token 存入 DB 或redis中。如果需要让某个 token 失效就直接从 redis 中删除这个 token 即可。但是,这样会导致每次使用 token 发送请求都要先从redis中查询 token 是否存在的步骤,而且违背了 JWT 的无状态原则,不可取。
② 黑名单机制:使用内存数据库比如 redis 维护一个黑名单,如果想让某个 token 失效的话就直接将这个 token 加入到 黑名单 即可。然后,每次使用 token 进行请求的话都会先判断这个 token 是否存在于黑名单中。
针对续签问题:
① 类似于 Session 认证中的做法: 假设服务端给的 token 有效期设置为30分钟,服务端每次进行校验时,如果发现 token 的有效期马上快过期了,服务端就重新生成 token 给客户端。客户端每次请求都检查新旧token,如果不一致,则更新本地的token。这种做法的问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好。每次请求都返回新 token :这种方案的的思路很简单,但是,很明显,开销会比较大。
② 用户登录返回两个 token :第一个是 acessToken ,它的过期时间比较短,不如1天;另外一个是 refreshToken 它的过期时间更长一点比如为10天。客户端登录后,将 accessToken和refreshToken 保存在客户端本地,每次访问将 accessToken 传给服务端。服务端校验 accessToken 的有效性,如果过期的话,就将 refreshToken 传给服务端。如果 refreshToken 有效,服务端就生成新的 accessToken 给客户端。否则,客户端就重新登录即可。
说明:JWT 最适合的场景是不需要服务端保存用户状态的场景,但是如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。
微服务架构
微服务架构下服务端根据业务拆分为多个服务,除了公司内部服务外,外部客户或者第三方也通过api网关统一转发请求,在这个阶段系统需要提供跨系统单点登录、第三方授权登录等基础能力。在这种架构下后端建立单独的认证授权中心。 目前实现统一身份认证和授权的技术手段较多,总体可以归纳为以下几类。
传统的 Cookie + Session 解决方案 ,有状态会话模式
- 认证授权流程:
同分布式服务架构中的“Session共享方案”
- 适合场景:
同分布式服务架构中的“Session共享方案”
- 常用实现:
同分布式服务架构中的“Session共享方案”
- 缺陷:
分布式 Session 是老牌的成熟解决方案,但因其状态化通信的特性与微服务提倡的API导向无状态通信相互违背,且共享式存储存在安全隐患,因此微服务一般不太采用
JWT+网关撤销令牌方案,无状态交互模式
- 认证授权流程:
同分布式服务架构中的“客户端token方案”,只是在该基础上,加上API网关令牌失效和令牌续签的机制,参考分布式服务架构中的“Session共享方案”的“如何解决”部分。
- 适合场景:
同分布式服务架构中的“客户端token方案”
- 常用实现:
同分布式服务架构中的“客户端token方案”
- 缺陷:
同分布式服务架构中的“客户端token方案”
JWT + OAuth2.0 +CAS方案
CAS是单点登录的解决方案,单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。CAS共涉及角色有:CAS Client(下文提到的系统A等)、User、CAS Server(认证中心)。CAS 是一个认证框架,其本身定义了一套灵活完整的认证流程,但其兼容主流的认证和授权协议如 OAuth2、SAML、OpenID 等,因此一般采用 CAS + OAuth2 的方案实现 SSO 和授权登录。
- 认证授权流程:
1.用户访问系统A;
2.系统A发现用户没有登录,也没有ticket,重定向到认证中心;有ticket跳转 第7步;
3.认证中心发现用户并未登录,展示登录页面;
4.用户登录;
5.认证中心登录成功,带着生成的ticket,重定向到之前的系统A页面;
6.系统A检查登录,还是未登录,但存在ticket。系统A带着ticket和认证中心进行校验;
7.认证中心返回对应的用户名;
8.系统A检查返回的用户名是否只有一个且不为空,若是,则返回给用户指定的资源信息;若不是,则跳转 第2步。
- 常用实现
spring security + CAS
OAuth2.0协议考虑到了微服务认证中的方方面面,提供的多种授权模式。这种方案的优点是安全性好,是业内成熟的给第三方提供授权登录解决方案,但是实现成本和复杂度高。 OAuth2.0提供了4种授权模式,能够适应多种场景,作为基于令牌的安全框架,可以广泛用于需要统一身份认证和授权的场景。 在 OAuth2.0 的实施过程中,一般会采用 JWT 作为令牌的主要标准。以文章分享举个例子,你在(登录后)浏览某论坛时,遇到了一篇好文章,想要分享给大家时,你需要登录(扫码或者登录用户名密码)第三方账户如微信来完成分享。
OAuth2.0还有个替代方案,OIDC,它是OpenID Connect的简称,OIDC=(Identity, Authentication) + OAuth 2.0。它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。暂时没研究,有兴趣的朋友可以查查。
- 认证授权流程:
1、在点击分享链接时,主服务器会直接(接口)请求第三方服务器,第三方服务器会校验主服务器上的用户此时是否授权给自己(第三方);
2、没有授权信息,用户登录(扫描或者密码)。
3、主服务器拿着用户的登录信息去第三方确认认证授权(密码是否正确、是否授权)。
4、认证失败,密码错误。(重新登录)
5、认证成功(确认授权),第三方认证服务会返回的授权码。
6、主服务器带着授权码请求第三方资源服务器,第三方资源服务器会返回指定的URI(分享界面)。
7、用户操作分享操作(填写自己的话语),点击分享按钮完成。
- 常用实现
spring security +OAuth2.0
OAuth2.0提供了4种授权模式,如下:
- 授权码模式
授权码模式相对其他三个模式来说是功能最完整,流程最安全严谨的授权方式。它的特点是通过客户端的后台服务器与服务提供商的认证服务器进行交互:
A. 用户访问客户端,客户端将用户导向认证服务器,需要携带客户端ID凭证和重定向URI。
B. 用户选择是否给予客户端授权。
C. 假设用户给予授权,认证服务器将用户导向事先指定的重定向URI,同时附上一个授权码。
D. 客户端收到授权码后,携带事先指定的重定向URI和授权码向认证服务器申请令牌。
E. 认证服务器核对授权码和重定向URI,确认无误后,向客户端颁发访问令牌(access token)和刷新令牌(refresh token)。
这里的resource owner代表客户,user-agent代表客户使用的访问工具如浏览器或App,client指第三方客户端
- 简化模式
简化模式不通过服务端程序来完成,比授权码模式减少了“授权码”这个步骤,直接由浏览器发送请求获取令牌,令牌对访问者是可见的,且客户端不需要认证,这种模式一般用于无后端应用,如手机/桌面客户端程序、浏览器插件
A. 用户访问客户端,客户端将用户导向认证服务器,需要携带客户端ID凭证和重定向URI。
B. 用户选择是否给予客户端授权。
C. 假设用户给予授权,认证服务器将用户导向事先指定的重定向URI,并在URI的Hash部分包含了访问令牌(Fragment)。
D. 浏览器向资源服务器发出请求,其中不包含事先收到的Hash部分(Fragment)。
E. 资源服务器返回一段脚本,其中包含的代码可以获取Hash部分中的令牌。
F. 浏览器执行事先获取的脚本,提取出令牌
G. 浏览器将令牌发送给客户端。
- 密码模式
密码模式中,用户向客户端提供用户名和密码,客户端使用这些信息,直接向认证服务器索要授权。这种模式违背了前面提到的微服务安全要解决的问题(不暴露用户名和密码),但是在一些用户对客户端高度信任的情况下,例如公司内部软件间的授权下,使用这种模式也是适用的
A. 用户向客户端提供用户名和密码。
B. 客户端将用户名和密码发送给认证服务器,向认证服务器索要令牌。
C. 认证服务器确认无误后,向客户端提供访问令牌。
- 客户端模式
客户端模式是客户端以自己的名义去授权服务器申请授权令牌,并不是完全意义上的授权。一般不适用这种模式
A. 客户端向认证服务器进行身份认证,并要求获取访问令牌。
B. 认证服务器确认无误后,向客户端提供访问令牌。
- 刷新令牌
如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌
A. 客户端向认证服务器进行身份认证,并要求获取访问令牌。
B. 认证服务器确认无误后,返回访问令牌和一个刷新令牌。
C. 客户端通过访问令牌访问受保护资源。
D. 如果访问令牌未过期,则向客户端提供资源服务。
E. 客户端通过访问令牌访问受保护资源。
F. 如果访问令牌过期,受保护资源服务器返回Invalid Token Error。
G. 客户端得到上方的错误后,通过刷新令牌向授权服务器申请一个新的访问令牌。
H. 认证服务器确认无误后,返回访问令牌和一个刷新令牌。
相关推荐
- C++开发必知的内存问题及常用的解决方法-经典文章
-
1.内存管理功能问题由于C++语言对内存有主动控制权,内存使用灵活和效率高,但代价是不小心使用就会导致以下内存错误:omemoryoverrun:写内存越界odoublefree:同一块内...
- 缓存用不好,系统崩得早!10条军规让你成为缓存高手
-
凌晨三点,我被电话惊醒:“苏工!首页崩了!”监控显示:缓存命中率0%,数据库QPS10万+,线程阻塞2000+。根本原因竟是同事没加缓存!不会用缓存的程序员,就像不会刹车的赛车手——...
- 彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏
-
作为C/C++开发人员,内存泄漏是最容易遇到的问题之一,这是由C/C++语言的特性引起的。C/C++语言与其他语言不同,需要开发者去申请和释放内存,即需要开发者去管理内存,如果内存使用不当,就容易造成...
- Java中间件-Memcached(Java中间件大全)
-
一、知识结构及面试题目分析缓存技术的大规模使用是互联网架构区别于传统IT技术最大的地方,是整体高并发高性能架构设计中是重中之重的关键一笔,也是互联网公司比较偏好的面试题目。按照在软件系统中所处位置...
- linux内存碎片防治技术(linux内存碎片整理)
-
推荐视频:90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc原理剖析Linux内核内存分配与回收Linuxkernel组织管理物理内存的方式是buddysystem(伙...
- Redis主从架构详解(redis主从配置详细过程)
-
Redis主从架构搭建Redis主节点配置创建主节点目录(/opt/redis-master),复制redis.conf到该目录下,redis.conf配置项修改#后台启动daemonizeyes...
- 揭开CXL内存的神秘面纱(内存c1)
-
摘要:现代数据中心对内存容量的高需求促进了内存扩展和分解方面的多条创新线,其中一项获得极大关注的工作是基于ComputeeXpressLink(CXL)的内存扩展。为了更好地利用CXL,研究人员建...
- 一文彻底弄懂 TPS RPS QPS(tps cps)
-
以下是关于RPS、QPS、TPS的核心区别与关联的总结,结合实际场景和优化建议:一、核心定义与区别RPS:RequestsPerSecond每秒请求数客户端到服务器的完整请求数量Web服务...
- 用Redis的“集合”找出你和朋友的“共同关注”
-
你是不是在刷抖音、微博、小红书的时候,常常会看到这样的提示:“你和XXX有共同关注的博主/朋友”?或者当你关注了一个新的明星,系统会推荐“你的朋友YYY也关注了这位明星”?这个看似简单的功能背后,其实...
- WOT2016彭哲夫:科班出身开发者对运维人员的期许
-
“运维与开发”是老生常谈的话题,前几天和一个运维人聊天,TA说一些公司运维岗位都不公开招聘了,这让众多运维人员情何以堪?是运维的岗位真的饱和了?是找到合适的运维人才难?还是有这样那样的因素?带着这些疑...
- Java程序员最常用的20%技术总结(java程序员要掌握什么)
-
我听说编程语言,经常使用的是其中20%的技术。在Java这门语言中,这20%包括哪些内容?找到一份Java初级程序员的工作,有哪些是必须掌握的,有哪些是可以现学现卖的?一个完整的Javaweb项目,有...
- 秒杀系统实战(四)| 缓存与数据库双写一致性实战
-
前言微笑挖坑,努力填坑。————已经拥有黑眼圈,但还没学会小猪老师时间管理学的蛮三刀同学本文是秒杀系统的第四篇,我们来讨论秒杀系统中「缓存热点数据」的问题,进一步延伸到数据库和缓存的...
- 头条评论精灵翻牌子(头条评论精灵翻牌子怎么弄)
-
关于“头条评论精灵翻牌子”功能,这通常是指平台通过算法或运营手段,将用户的优质评论随机或定向推送到更显眼的位置(如信息流顶部、独立曝光位等),以提升互动率和用户参与感。以下是详细解析和建议:一、功能理...
- 15个程序员们都应该知道的大模型高级提示词指令模板和示例
-
作为程序员你如何写大模型指令?你写的指令是不是更专业呢?下面是15个程序员使用的专业的大模型指令,如果早知道可以能节省你很多时间。这些指令可以用在chatgpt,deepseek等大模型。1.一键...
- MyBatis-Plus内置的主键生成策略有大坑,要注意!
-
昨天小伙伴使用Mybaits-Plus开发的项目线上(集群、K8S)出现了主键重复问题,其报错如下:Mybatis-Plus启动时会通过com.baomidou.mybatisplus.core.to...
你 发表评论:
欢迎- 一周热门
-
-
Redis客户端 Jedis 与 Lettuce
-
高并发架构系列:Redis并发竞争key的解决方案详解
-
redis如何防止并发(redis如何防止高并发)
-
开源推荐:如何实现的一个高性能 Redis 服务器
-
redis安装与调优部署文档(WinServer)
-
Redis 入门 - 安装最全讲解(Windows、Linux、Docker)
-
一文带你了解 Redis 的发布与订阅的底层原理
-
Redis如何应对并发访问(redis控制并发量)
-
oracle数据库查询Sql语句是否使用索引及常见的索引失效的情况
-
Java SE Development Kit 8u441下载地址【windows版本】
-
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)