尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

IdentityServer4认证授权之授权码模式(Authorization Code+PKCE)

IdentityServer4认证授权之授权码模式(Authorization Code+PKCE)
📅 发布时间:2026/6/19 18:27:15

前言

1.配置服务认证授权

订单服务(Ordering.API)配置了认证授权,所以我们使用Scalar调试接口的时候也需要认证服务(Identity.API)颁发的token,上面的测试就是401无权限

首先我们再回忆下我们认证授权配置了那些:

  • 认证服务(Authority):我们本地启动的Identity.API,其他服务认证授权配置Identity.API的地址即可。
  • 使用Https协议获取认证中心(Authority )元数据(RequireHttpsMetadata):原来这里是false,访问不验证https,为了多学习我们设置为true,本身Identity.API启动就是使用的https协议
  • 订阅人(Audience):确保认证服务Identity.API颁发的token是发给我的(订单服务),就是我们在appsettings.json中配置"Audience": "orders"。简单理解:什么服务就配置什么服务的标识,但是认证服务同时也要有此标识。确保这个Token 是发给当前 API 的,而不是其他服务。验证签发token的aud。
  • 签发者(Issuers):确保Token是由受信任的认证中心签发。验证签发token的iss。

image-20251104012258084

还需要再回忆一下认证服务(Identity.API)中的客户端配置,找到orderingswaggerui配置

image-20251104014215886

然后我们启动认证服务,在..\eShop\src\Identity.API目录下运行以下命令:

dotnet run --urls https://localhost:5243/

image-20251103193457394

2.配置授权码模式(Authorization Code + PKCE)

隐式模式(Implicit)已经被淘汰了,eShop 官方示例用 Implicit,是为了演示方便(快速看到授权效果),让 Swagger UI(或浏览器)/Scalar能够直接拿到 Access Token,方便开发和测试。

在 OAuth 2.1 规范中(2023 年正式发布),Implicit 模式已被标记为弃用:

  • Access Token 暴露在 URL;
  • 无法安全刷新;
  • 浏览器中易被脚本窃取;
  • 无法防止中间人攻击。

所以现代标准中 强制推荐改用 Authorization Code + PKCE。

既然学习,我们也看看授权码模式(Authorization Code + PKCE),我们就以购物车服务(Basket.API)为例,因为购物车的Scalar也是我们为了学习加上的,购物车服务(Basket.API)因为使用了Grpc,所以只能使用https协议,我们把接口也加上了api版本

image-20251104235344290

先添加以下配置:

 // 授权类型:Authorization Code + PKCEAllowedGrantTypes = GrantTypes.Code,// SPA/Scalar 客户端不保存 secret,所以不要求 client_secretRequireClientSecret = false,// 强制使用 PKCE(安全性必须)RequirePkce = true,// 是否显示用户同意授权页面RequireConsent = true, // 强制每次授权确认// token 生命周期和刷新控制(可选)AllowOfflineAccess = false, // 如果暂时不需要 refresh token// 允许跨域请求的 originAllowedCorsOrigins ={"https://localhost:5221"  // Scalar / Swagger UI 所在的域名},

为什么授权码模式(Authorization Code + PKCE)会触发跨域?隐式模式(Implicit )不需要(这是我调试过程遇到的问题,我提前记录一下)

在 Implicit 流 下:

  • 浏览器通过 302 重定向 + URL fragment 获取 token
  • 不走 JS Ajax,所以不会触发 CORS

在 Authorization Code + PKCE 下:

  • 前端 SPA 需要用 JS 通过 POST /connect/token 来交换 code → access_token
  • 浏览器 JS 发起的是跨域 AJAX 请求
  • IdentityServer 如果没有允许该 Origin,就报 CorsPolicyService did not allow origin: ...

image-20251105000220581

然后配置回调地址(RedirectUris)和允许访问的的API范围(AllowedScopes)

为什么需要配置 RedirectUris?

  • OAuth2 / OIDC 协议要求每个客户端注册 回调地址(redirect_uri)。

  • 当用户在 IdentityServer 授权成功后,浏览器会重定向到这个地址,并带上 code 或 token。

  • 严格匹配:IdentityServer 会检查请求中的 redirect_uri 是否在客户端注册列表里,否则会报:Invalid redirect_uri

为什么还要配置 openid / profile scopes?

这些 scope 来自 OpenID Connect (OIDC) 协议:

  • openid → 表示这是一个 OIDC 请求(IdentityServer 会返回 id_token)
  • profile → 请求用户信息(如名字、头像等)

区别于普通 API scope:

  • API scope(比如 basket)只控制访问后端 API
  • openid/profile 用于获取用户身份信息(JWT 中的 claims)

如果你的前端只需要访问 API,不关心用户信息,可以不用 openid/profile,openid/profile 可以根据需要决定是否保留。

image-20251105000716645

定义一个名为 "basket" 的受保护 API,并指定访问它需要 "basket" 这个 scope。

image-20251105001310689

OAuth2新增授权码模式(Authorization Code + PKCE )

image-20251105001538818

RequireAuthorization:给这个 API 分组下的所有端点应用授权策略,也就是需要用户已经登录或具备某些权限才能访问这些接口。

var api = vApi.MapGroup("api/Basket").HasApiVersion(1, 0).HasApiVersion(2, 0).RequireAuthorization();

image-20251105003204676

如果配置RequireAuthorization()没有token访问接口返回401(无权限)

image-20251105003342117

所有代码配置完成后,启动购物车服务(Basket.API),打开Scalar,选择OAuth2,发现多了一种授权方案(Authorization Code)

跟之前一样配置:Client ID、Use PKCE、Scopes

Client Secret 可选

  • 对于 SPA 或前端客户端(比如 Scalar 文档 UI、Swagger UI),不存储密钥是推荐做法,因为前端代码无法安全保管 secret。

  • 所以在IdentityServer中,你可以配置 RequireClientSecret = false。

  • 如果你在 Scalar 上看到 Client Secret: XYZ123,那只是生成的示例,并不是必须的。

PKCE 强制使用 SHA-256

  • PKCE(Proof Key for Code Exchange)是 Authorization Code 流的增强安全机制,用于前端应用防止授权码被截获。
  • PKCE 流程里有一个 code_challenge,必须经过 SHA-256 哈希(S256)生成,原始的 plain 方法被现代安全标准弃用。
  • 因此 IdentityServer 会要求 code_challenge_method = S256,不能用 plain,否则报错:code_challenge_method of plain is not allowed

image-20251105001926111

输入用户名和密码,然后点击登录

image-20251105002848800

再点击Yes,Allow(允许授权)

image-20251105002929930

打开/api/Basket/{customerId},测试一下,查询正常

image-20251105003038439

3.授权码模式流程(Authorization Code + PKCE)

在查看 OpenAPI 规范文档时,我们为 oauth2 安全方案配置了两种授权模式:Implicit 和 Authorization Code,分别对应浏览器直接获取 token 和通过授权码交换 token 的安全流程,并指定了 basket API 的访问范围。

https://localhost:5221/openapi/v1.json

image-20251105004034522

先关闭认证服务(Identity.API),然后设置Client ID、Use PKCE、Scopes,点击Authorize

查看Scalar发起的授权请求:

  • response_type=code:授权码模式。
  • scope:请求访问的范围。
  • code_challenge & code_challenge_method:PKCE,客户端生成随机字符串和散列,服务器用来校验。
  • redirect_uri:授权成功后回调地址。
  • state:防 CSRF,同时保持请求上下文
  • client_id:当前客户端的唯一标识
# 原请求
https://localhost:5243/connect/authorize?response_type=code&code_challenge=3_V716AyAbS7uKOkhK6jDTW7Ho8As2_zq6EOBA_i7jQ&code_challenge_method=S256&redirect_uri=https%3A%2F%2Flocalhost%3A5221%2Fscalar%2Fv1&client_id=basketswaggerui&state=78jzgb2i&scope=basket
# 解码后 redirect_uri加密了
https://localhost:5243/connect/authorize?
response_type=code&
code_challenge=3_V716AyAbS7uKOkhK6jDTW7Ho8As2_zq6EOBA_i7jQ&
code_challenge_method=S256&
redirect_uri=https://localhost:5221/scalar/v1&
client_id=basketswaggerui&
state=78jzgb2i&
scope=basket

image-20251105004502293

启动认证服务(Identity.API)和购物车服务(Basket.API),设置Client ID、Use PKCE、Scopes,点击Authorize

没登录前:Showing login: User is not authenticated(显示登录页,用户没有认证)

image-20251105005336634

登陆成功后:Showing consent: User has not yet consented(显示授权:用户未授权)

image-20251105005723209

登录&授权后:Scalar发送 POST 请求到 Token 端点

  • client_id:客户端唯一标识
  • redirect_uri:回调地址,必须匹配注册信息
  • code:授权码,用于换取 Access Token
  • grant_type:授权模式,这里是授权码模式(authorization_code)
  • code_verifier:PKCE 验证码,保证授权码安全
POST https://localhost:5243/connect/token
client_id=basketswaggerui&
redirect_uri=https%3A%2F%2Flocalhost%3A5221%2Fscalar%2Fv1&
code=32BAD9BF9537F37C142CAC44066BFC80F5A81DDBB61B74E06445FA61881D0A85-1&
grant_type=authorization_code&
code_verifier=5JddRWZjBe72ixVPwZMxIQblPyhe_MivmcNUQFa2LEI

为什么授权码模式(Authorization Code + PKCE)会触发跨域?隐式模式(Implicit )不需要(这是我调试过程遇到的问题,我提前记录一下)

上面记录了这个问题,就是因为Scalar客户端发起了Ajax请求获取token,所以认证服务(Identity.API)需要配置AllowedCorsOrigins

image-20251105005842494Scalar设置Access Token,所有api调用就可以使用这个Access Token

image-20251105010600233

SPA/Scalar 通常不使用 Refresh Token,是因为浏览器无法安全存储长期凭证,短期 Access Token + PKCE 重新授权比使用 Refresh Token 更安全。

image-20251105010745695

流程说明

步骤 Authorization Code + PKCE Flow
1 用户点击 Authorize
2 跳转 IdentityServer 登录
3 如果未登录 → 输入用户名/密码
4 用户同意授权
5 IdentityServer 重定向回客户端(带 授权码 code)
6 客户端使用 code + code_verifier 向 IdentityServer Token Endpoint 交换 Access Token
7 IdentityServer 返回 Access Token(可选 ID Token)
8 客户端使用 Access Token 调用受保护 API

📌 创作不易,感谢支持!

每一篇内容都凝聚了心血与热情,如果我的内容对您有帮助,欢迎请我喝杯咖啡☕,您的支持是我持续分享的最大动力!

💬 加入交流群(QQ群):576434538

微信打赏

相关新闻

  • Git推送从失败到成功的解决方案
  • OBDSTAR P003+ Kit for DC706 Tablets: Simplify ECU, EEPROM, Flash IMMO Data Diagnostics Programming
  • Fast Easy Electric Oil Siphon Pump: Professional Fluid Transfer for Cars, Motorcycles Boats

最新新闻

  • 北京摄影学校精选推荐,2026年北京靠谱的摄影学校推荐 - 教育信息网
  • 深度解析macOS滚动事件拦截:构建专业级定制插件的完整指南
  • 常州多年黄金回收攻略,三十年实体经营,收的顶本地口碑有保障 - 奢侈品回收测评
  • 01_系统架构设计
  • 如何免费实现专业级直播抠像:obs-backgroundremoval插件完全指南
  • 新手必看!抖音保存视频到相册的详细步骤技巧 - 工具软件使用方法推荐

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号