0

0

一文详解怎么实现微服务鉴权

藏色散人

藏色散人

发布时间:2023-01-27 08:30:02

|

2604人浏览过

|

来源于juejin

转载

本篇文章给大家带来了关于鉴权的相关知识,其中主要介绍了微服务中鉴权的实现思路是什么?又有什么好的方案来实现呢?下面一起来看一下,希望对大家有帮助。

最近刚好有小伙伴在微信上问到这个问题,我就来和大家聊一聊,本文主要和小伙伴们聊一聊思路,不写代码,小伙伴们可以结合我之前的文章,应该能够自己写出来本文的代码。当然,思路也只是我自己的一点实践经验,不一定是最完美的方案,欢迎小伙伴们在留言中一起探讨。

1. 认证与授权

首先小伙伴们知道,无论我们学习 Shiro 还是 Spring Security,里边的功能无论有哪些,核心都是两个:

  • 认证

  • 授权

所以,我们在微服务中处理鉴权问题,也可以从这两个方面来考虑。

1.1 认证

认证,说白了就是登录。传统的 Web 登录是 Cookie+Session 的方案,这种方案依赖于服务器本地内存,在微服务中,由于服务众多,这种方案显然不再合适。

可能会有小伙伴说用 Redis+SpringSession 做 Session 共享,这是个办法,但是不是最佳方案,因为这种方案的性能以及可扩展性都比较差。

所以,微服务中的认证,还是建议使用令牌的方式,可以选择 JWT 令牌,这也是目前使用较多的一种方案。但是熟悉 JWT 的小伙伴都知道,纯粹的无状态登录无法实现注销,这就很头大,所以在实际应用中,单纯的使用 JWT 是不行的,一般还是要结合 Redis 一起,将生成的 JWT 字符串在 Redis 上也保存一份,并设置过期时间,判断用户是否登录时,需要先去 Redis 上查看 JWT 字符串是否存在,存在的话再对 JWT 字符串做解析操作,如果能成功解析,就没问题,如果不能成功解析,就说明令牌不合法。

这样有状态登录+无状态登录混在一起的方式,虽然看起来有点不伦不类,但是就当下来说,这个折衷的办法算是一个可行的方案了。

其实,上面的方案,说白了,跟传统的 Cookie+Session 没什么两样,思路几乎都是完全 copy 的:传统的 Session 用 Redis 代替了;传统穿梭于服务端和浏览器之间的 jsessionId 被 JWT 字符串代替了;传统的 jsessionId 通过 Cookie 来传输,现在的 JWT 则通过开发者手动设置后通过请求头来传输;传统的 Session 可以自动续签,现在用 JWT 就是手动续签,每次请求到达服务端的时候,就去看下 Redis 上令牌的过期时间,快过期了,就重新设置一下,其他都一模一样。

这是认证方案的选择。

1.2 授权

微服务中授权,也可以使用 Shiro 或者 Spring Security 框架来做,省事一些。考虑到微服务技术栈都是 Spring 家族的产品,所以在权限框架这块也是建议大家首选 Spring Security(如果有小伙伴对 Spring Security 还不熟悉的话,可以在微信公众号后台回复 ss,有教程)。

当然,如果觉得 Spring Security 比较复杂想自己搞的话,也是可以的。自己搞的话,也是可以借助于 Spring Security 的思路的,松哥最近的一个项目就是这样:

请求到达微服务之后,先找到当前用户的各种信息,包括当前用户所拥有的角色和权限等信息,然后存入到和当前线程绑定的 ThreadLocal 对象中。另一方面自定义权限注解和角色注解,在切面中对这些注解进行解析,检查当前用户是否具备所需要的角色/权限等。

当然,如果你使用了 Spring Security 的话,上面这个就不需要自定义注解了,直接使用 Spring Security 中自带的即可,还可以体验 Spring Security 中更多的丰富的安全功能。

2. 认证服务

那么认证和授权在哪里做?

先来说认证,认证我们可以简单分为两个步骤:

  • 登录

  • 校验

2.1 登录

一般来说,登录我们可以单独做一个认证服务。当登录请求到达网关之后,我们将之转发到认证服务上,完成认证操作。

Otter.ai
Otter.ai

一个自动的会议记录和笔记工具,会议内容生成和实时转录

下载

在认证服务上,我们就去检查用户名/密码是否 OK,用户状态是否都 OK,都没问题的话,生成 JWT 字符串,同时再把数据存入到 Redis 上,然后把 JWT 字符串返回。

如果系统有注册功能的话,注册功能也是放在这个微服务上来完成。

2.2 校验

校验是指每一个请求到达的时候,校验用户是否已经登录。

这个当然可以和 2.1 放到一起去做,但是松哥不建议。问题在于,假如是一个创建订单的请求,这个请求原本是要经过网关转发到订单服务上的,但是,此时就得先在网关上调用 2.1 小节的服务进行登录校验,没问题再转发到订单服务上,这样做很明显很费事,也不合理。

一个比较好的办法是直接在网关上去校验请求的令牌是否合法,这个校验本身也比较容易,校验令牌是否合法,我们只需要看 Redis 上是否存在这个令牌,并且这个 JWT 令牌能够被顺利解析就行,这个操作完全可以在网关上做。

以 Gateway 网关为例,我们可以自定义全局过滤器,在全局过滤器中校验每一个请求的令牌,校验通过了,再进行请求的转发,否则就不转发。

校验通过之后,在转发到具体的微服务之后,我们可以将解析出来的用户 id 以及用户名等信息放到请求头中,然后再转发,这样到达各个具体的微服务之后,就知道这个请求是谁发来的,这人都有哪些角色/权限,方便做下一步的权限校验。

松哥的做法是定义了一个公共模块,所有的微服务都依赖这个公共模块,这个公共模块中定义了一个拦截器,会拦截下来每一个请求,从请求头中取出用户 ID,然后从 Redis 中拿到具体的用户信息,存入到 ThreadLocal 中,这样在后续的方法调用中,如果需要判断用户是否具备某一个权限,就可以通过 ThreadLocal 去获取了。

大致上就是这样一个流程。

3. 授权服务

授权没法放到网关上做,还是得在各个微服务上去完成。

微服务上的授权我们又可以将之大致上分为两类:

  • 前端发送来的请求(外部请求)。

  • 别的微服务发送来的请求(内部请求)。

3.1 外部请求

对于外部请求来说,就按正常的权限校验对待就行了,自定义注解亦或者使用 Spring Security 等框架都是可以的,如果是自定义注解的话,就结合 AOP 一起,定义切面自己去处理权限注解,当然,这些功能基本上每一个微服务都是需要的,所以可以将之抽取成为一个公共的模块,在不同的微服务中依赖即可。

3.2 内部请求

对于内部的请求来说,正常是不需要鉴权的,内部请求可以直接处理。问题是如果使用了 OpenFeign,数据都是通过接口暴露出去的,不鉴权的话,又会担心从外部来的请求调用这个接口,对于这个问题,我们也可以自定义注解+AOP,然后在内部请求调用的时候,额外加一个头字段加以区分。

当然,内部请求到达微服务的时候,也是需要进行认证的,就行请求从网关转发到每一个具体的微服务上时需要认证一样,不过很明显,我们没必要每次使用 OpenFeign 调用别的服务的时候,都去传一堆认证信息,我们可以通过实现 feign.RequestInterceptor 接口来定义一个 OpenFeign 的请求拦截器,在拦截器中,统一为 OpenFeign 请求设置请求头信息。

好啦,关于微服务中的鉴权,我们目前是这么做的,欢迎小伙伴们留言一起探讨。

推荐学习:《小程序视频教程》《Java视频教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
高级PHP之Swoft入门到微服务
高级PHP之Swoft入门到微服务

共56课时 | 3.8万人学习

webman初步使用及后台搭建
webman初步使用及后台搭建

共15课时 | 2.3万人学习

从0开始进入PHP的世界
从0开始进入PHP的世界

共89课时 | 12.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号