新闻详情

新闻详情

首页 / 资讯中心 / 详情

OAuth学习之,自定义实现Client:从零搭建可调试的授权码客户端

发布时间:2026/9/27 20:01:48来源:尧图网络
OAuth学习之,自定义实现Client:从零搭建可调试的授权码客户端
1. 为什么我要自己写一个 OAuth ClientOAuth 2.0 授权码模式Authorization Code Grant是后端开发绕不开的一块内容。很多同学第一次接触时直接拿现成框架的默认配置跑通就结束了结果一旦要改 client 存储方式、要加缓存、要自定义 redirect_uri 校验就完全不知道从哪下手。这篇就聚焦一件事自定义实现 OAuth 2.0 授权码模式里的 Client 端把 client_id、client_secret、redirect_uri、授权端点、令牌端点这些参数真正握在自己手里在本地完整跑通一次「授权码换 token」的链路。它适合谁适合已经能写 Spring Boot 接口、但对 OAuth 内部流转还停留在「照着文档抄配置」阶段的后端开发者。你不需要先精通 Spring Security 源码只要愿意跟着把配置骨架搭起来、发一次真实请求看返回就能把这条链路吃透。我自己的触发点很具体项目里 client_secret 存的是密文安全是安全了但调试时经常忘了原始值是什么改一次配置要重新生成一遍。于是我决定把 Client 的读取逻辑从框架默认实现里拆出来自己实现ClientDetailsService顺便加上 Redis 缓存让整个授权流程可控、可调试。下面这套骨架你可以直接复制改掉数据库和缓存部分就能用。2. 动手前先把 TaoToken 的接入信息准备好在写 Client 之前得先有一个能实际调用的授权服务端。我这里用 TaoToken 来做演示它提供标准的 OAuth 2.0 授权码流程端点清晰适合拿来练手。你需要先拿到两样东西API Key和接入文档。API Key 在控制台的 API Keys 页面创建接入文档里写清了授权端点、令牌端点的地址和参数格式。这两步是后面所有配置的基础建议先做完再往下看。创建和管理 Keyhttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite接入文档授权/令牌端点参数https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite注意client_secret 属于敏感凭据即使你像我一样为了方便调试想存明文也务必只在本地或隔离环境这么做生产环境仍然要走加密存储。拿到 Key 之后你手里应该有一组类似这样的信息client_id、client_secret、以及服务端暴露的 authorize 和 token 两个端点地址。把它们记下来下一步直接填进配置。3. 可复制的 Client 配置骨架3.1 自定义 ClientDetailsService 实现框架默认的JdbcClientDetailsService会去读官方指定的表结构字段固定、扩展麻烦。我选择自己实现ClientDetailsService接口从自己的sys_client表读数据并加一层 Redis 缓存。核心方法只有一个loadClientByClientId。Service public class CustomClientService implements ClientDetailsService { Autowired private ISysClientProvider sysClientProvider; Autowired private RedisUtil redisUtil; Autowired private PasswordEncoder passwordEncoder; private static final String CLIENT_REDIS_KEY SYS.CLIENT.; Override public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { SysClient client getOrSaveClientRedis(clientId); if (Objects.isNull(client)) { throw new NoSuchClientException(No client with requested id: clientId); } BaseClientDetails details new BaseClientDetails( clientId, client.getResourceIds(), client.getScope(), client.getAuthorizedGrantTypes(), client.getAuthorities(), client.getWebServerRedirectUri() ); details.setClientSecret(passwordEncoder.encode(client.getClientSecret())); return details; } public SysClient getOrSaveClientRedis(String clientId) { String key CLIENT_REDIS_KEY clientId; if (Boolean.TRUE.equals(redisUtil.hasKey(key))) { String json redisUtil.get(key); return JSONObject.parseObject(json, SysClient.class); } SysClient client sysClientProvider.getByClientId(clientId); if (Objects.isNull(client)) { return null; } redisUtil.set(key, JSONObject.toJSONString(client)); return client; } }这里有几个关键点值得说清楚。BaseClientDetails的构造参数顺序是固定的clientId、resourceIds、scope、authorizedGrantTypes、authorities、redirectUri。顺序错了会导致授权类型或回调地址读不到表现为授权请求被拒。authorizedGrantTypes里必须包含authorization_code否则授权码模式直接不生效。3.2 把自定义实现注入安全配置实现类写好后要在WebSecurityConfigurerAdapter的实现里把它注册成 Bean覆盖框架默认的 ClientDetailsService。Configuration EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { Autowired private CustomClientService customClientService; Bean public ClientDetailsService clientDetailsService() { return customClientService; } Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(/oauth/**).permitAll() .anyRequest().authenticated(); } }3.3 客户端参数对照表下面这张表把授权码模式里 Client 端要关心的参数列全配置时逐项核对能省掉大量排查时间。参数作用示例值client_id标识客户端身份my-client-001client_secret客户端密钥换 token 时校验本地可存明文生产加密redirect_uri授权后回调地址必须与注册值一致http://localhost:8080/callbackresponse_type固定为 codecodescope申请的权限范围read writegrant_type换 token 时固定为 authorization_codeauthorization_codecode授权码一次性使用服务端返回authorizedGrantTypes允许的授权类型authorization_code,refresh_token提示redirect_uri 必须和注册时完全一致包括端口和路径末尾斜杠差一个字符都会被拒。4. 跑一次授权码换 token 验证配置就绪后用两步请求把链路走通。第一步拿授权码第二步用授权码换 token。4.1 获取授权码在浏览器里访问授权端点带上 client_id、redirect_uri、response_type 和 scopeGET https://taotoken.net/oauth/authorize ?client_idmy-client-001 redirect_urihttp://localhost:8080/callback response_typecode scoperead用户确认授权后浏览器会跳转到你的 redirect_uri并在 URL 上附带一个 code 参数http://localhost:8080/callback?codeA1B2C3D4E5这个 code 有效期很短通常几分钟且只能使用一次。拿到后立刻进行下一步。4.2 用授权码换取 token用 POST 请求令牌端点把 code 换成 access_tokencurl -X POST https://taotoken.net/oauth/token \ -H Content-Type: application/x-www-form-urlencoded \ -d grant_typeauthorization_code \ -d codeA1B2C3D4E5 \ -d redirect_urihttp://localhost:8080/callback \ -d client_idmy-client-001 \ -d client_secretyour_client_secret成功时返回类似下面的 JSON{ access_token: eyJhbGciOi..., token_type: Bearer, expires_in: 3600, refresh_token: def50200..., scope: read }看到 access_token 就说明整条链路通了。你可以拿这个 token 去调用受保护资源验证它确实生效。如果返回 401 或 invalid_grant先别急着改代码对照下一节的排查清单逐项检查。5. 本篇常见错误排查invalid_clientclient_id 或 client_secret 不匹配。检查数据库里存的 secret 和请求里传的是否一致注意passwordEncoder.encode后存的是密文如果换 token 时框架又做了一次比对明文和密文对不上就会报这个错。调试阶段可以临时关掉编码器确认是编码问题后再恢复。invalid_grantcode 已过期、已被使用或 redirect_uri 与获取 code 时不一致。授权码是一次性的重复提交同一个 code 必然失败重新走一遍授权拿新 code。unauthorized_client该 client 没有被授权使用 authorization_code 模式。检查authorizedGrantTypes字段里是否包含authorization_code很多人只填了password或refresh_token。redirect_uri_mismatch回调地址和注册值不一致。逐字符比对特别注意 http 与 https、端口号、末尾斜杠。缓存导致配置不生效改了数据库里的 client 配置但 Redis 里还是旧值。我踩过的坑就是这里改完配置忘了清缓存排查了半天。调试时先删掉SYS.CLIENT.开头的 key 再重试。注意如果授权请求直接返回登录页而不是授权确认页通常是安全配置把/oauth/**拦住了确认permitAll已生效。6. 把链路跑通之后到这里一个可调试的 OAuth 2.0 授权码 Client 就搭起来了自定义ClientDetailsService负责读 client、Redis 做缓存、安全配置完成注入最后用两次请求验证了授权码换 token 的完整链路。这套骨架的价值在于每一环你都能打断点、看日志、改参数而不是被框架的黑盒吞掉错误信息。如果你在接入过程中卡在端点参数或返回码上直接翻接入文档对照比在网上搜零散答案快得多https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite想先直观看看模型对话和 token 返回长什么样可以在模型对话页里试一次请求观察返回结构https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite如果你打算把这条链路接到长期的编码工具或 Agent 里反复手动换 token 会很烦用 Coding Plan 把凭据和调用统一管理起来更省事https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite最后留一个实用习惯每次改完 client 配置先清 Redis 再发请求能帮你避开一大半「配置明明改了却不生效」的假故障。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

哈佛 CS50 计算机科学导论笔记(一):用 TaoToken 统一 Key 跑通课程配置骨架 2026/9/27 20:51:49

哈佛 CS50 计算机科学导论笔记(一):用 TaoToken 统一 Key 跑通课程配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
SimHei.ttf字体下载安装全指南:跨平台兼容与排版问题解决 2026/9/27 20:51:43

SimHei.ttf字体下载安装全指南:跨平台兼容与排版问题解决

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
STM32开发如何找靠谱参考方案?盘点国内优质资源与避坑经验 2026/9/27 20:51:43

STM32开发如何找靠谱参考方案?盘点国内优质资源与避坑经验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
九联UNT403G/UNT413G刷机教程:GK6323V100C芯片U盘短接强刷全流程 2026/9/27 20:51:43

九联UNT403G/UNT413G刷机教程:GK6323V100C芯片U盘短接强刷全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
VoLTE高丢包根因诊断与四阶优化实战 2026/9/27 20:51:43

VoLTE高丢包根因诊断与四阶优化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
8259A可编程中断控制器初始化详解:ICW寄存器配置与实战避坑 2026/9/27 20:50:58

8259A可编程中断控制器初始化详解:ICW寄存器配置与实战避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉