多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Sa-Token HTTP 请求扩展插件指南:从 SaHttpTemplate 到 SSO 模式三的高效接入

Sa-Token HTTP 请求扩展插件指南:从 SaHttpTemplate 到 SSO 模式三的高效接入 Sa-Token HTTP 请求扩展插件指南从 SaHttpTemplate 到 SSO 模式三的高效接入【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token导读Sa-Token 在 SSO 模式三isHttp、单点注销、消息推送等跨系统调用场景中需要主动发起 HTTP 请求。为了让这种框架内部的 HTTP 调用与具体 HTTP 客户端解耦Sa-Token 自 1.43.0 起将调用逻辑抽象为SaHttpTemplate接口并通过 SPI 机制自动注入官方插件实现。本文以 sa-token-doc/plugin/http-extend.md 为主线结合sa-token-core与各插件源码系统讲解 HTTP 请求插件的选型、引入、自定义与排错帮助你在任何运行环境中为 Sa-Token 接上可用的 HTTP 能力。一、为什么要抽象一个SaHttpTemplateSa-Token 本身是纯 Java 实现、不依赖任何 Web 容器的框架。但在 SSO 模式三、单点注销、消息推送等场景中它需要代表当前应用去访问远端地址例如SSO 模式三Client 端通过 ticket 换取用户信息需要向 Server 发起 HTTP 请求单点注销一处登出需要通知其他子系统同步下线消息推送Server 与 Client 之间的业务消息传递。如果框架直接内置一个具体的 HTTP 客户端就会把第三方依赖强加给所有使用者。因此 Sa-Token 把发 HTTP 请求这一能力抽象成了接口// sa-token-core/src/main/java/cn/dev33/satoken/http/SaHttpTemplate.java public interface SaHttpTemplate { // get 请求 String get(String url); // post 请求form-data 格式参数 String postByFormData(String url, MapString, Object params); }该接口定义了两个方法get(url)与postByFormData(url, params)。从接口签名可以看出Sa-Token 的 HTTP 需求非常克制——只需要 GET 请求和 form-data 格式的 POST 请求返回值统一为字符串响应体文本这与 ticket 校验、消息推送这类请求-响应文本场景完全吻合。框架提供了静态工具类 SaHttpUtil内部委托给SaManager.getSaHttpTemplate()public static String get(String url) { return SaManager.getSaHttpTemplate().get(url); } public static String postByFormData(String url, MapString, Object params) { return SaManager.getSaHttpTemplate().postByFormData(url, params); }也就是说全框架所有 HTTP 调用最终都会汇聚到SaManager中持有的那一个SaHttpTemplate实例上。开发者只需要保证这个实例被正确设置即可。二、框架已提供的四个 HTTP 请求插件Sa-Token 官方仓库sa-token-plugin目录内置了四个 HTTP 插件分别整合不同的 HTTP 客户端库适用环境各不相同插件整合客户端适用环境核心实现类sa-token-forestForestSpring / 非 Spring 环境SSO 示例默认使用SaHttpTemplateForForestsa-token-okhttpsOkHttpsSpring / 非 Spring 环境SaHttpTemplateForOkHttpssa-token-rest-templateSpringRestTemplateSpring Boot 2 / 3 / 4 环境SaHttpTemplateForRestTemplatesa-token-rest-clientSpringRestClientSpring Boot 3.2 / Spring Framework 6.1 环境SaHttpTemplateForRestClient默认实现SaHttpTemplateDefaultImpl未实现 HTTP 调用未引入插件时会抛出「本地系统没有配置 http 请求处理器」错误码 30010。同一 classpath 只应存在一个 HTTP 插件多插件并存时后加载的会覆盖SaHttpTemplate。1. sa-token-forest轻量声明式 HTTP 客户端Forest 是一款轻量、声明式的 HTTP 客户端框架不依赖 Spring 容器因此适用于各种运行环境。Sa-Token 的 SSO 示例默认使用它。!-- Sa-Token 整合 Forest -- dependency groupIdcn.dev33/groupId artifactIdsa-token-forest/artifactId version${sa.top.version}/version /dependencyGradle 参考implementation cn.dev33:sa-token-forest:${sa.top.version}其实现类内部直接调用 Forest 的流式 APIOverride public String get(String url) { SaManager.log.debug(发起请求GET{}, url); String res Forest.get(url).executeAsString(); SaManager.log.debug(返回结果{}, res); return res; } Override public String postByFormData(String url, MapString, Object params) { SaManager.log.debug(发起请求POST{}\t参数{}, url, params); String res Forest.post(url).addBody(params).executeAsString(); SaManager.log.debug(返回结果{}, res); return res; }2. sa-token-okhttps基于 OkHttp 的 OkHttps 客户端OkHttps 是封装 OkHttp 的轻量 HTTP 框架同样不依赖 Spring 容器适用于 Spring / 非 Spring 环境。!-- Sa-Token 整合 OkHttps -- dependency groupIdcn.dev33/groupId artifactIdsa-token-okhttps/artifactId version${sa.top.version}/version /dependencyGradle 参考implementation cn.dev33:sa-token-okhttps:${sa.top.version}实现类使用OkHttps.sync(url)同步调用Override public String get(String url) { SaManager.log.debug(发起请求GET{}, url); String res OkHttps.sync(url).get().getBody().toString(); return res; } Override public String postByFormData(String url, MapString, Object params) { String res OkHttps.sync(url).addBodyPara(params).post().getBody().toString(); return res; }3. sa-token-rest-template整合 Spring RestTemplateRestTemplate 是 Spring 生态最经典的 REST 客户端适用于已经引入spring-web的 Spring Boot 2 / 3 / 4 环境。!-- Sa-Token 整合 RestTemplate需 Spring Boot 环境项目已引入 spring-web -- dependency groupIdcn.dev33/groupId artifactIdsa-token-rest-template/artifactId version${sa.top.version}/version /dependencyGradle 参考implementation cn.dev33:sa-token-rest-template:${sa.top.version}实现类内部new了一个独立的RestTemplate实例form-data 参数通过LinkedMultiValueMap承载null值会被转换为空字符串Content-Type 交由 RestTemplate 按MultiValueMap类型自动识别为application/x-www-form-urlencodedprivate final RestTemplate restTemplate new RestTemplate(); Override public String get(String url) { return restTemplate.getForObject(url, String.class); } Override public String postByFormData(String url, MapString, Object params) { MultiValueMapString, String formData new LinkedMultiValueMap(); params.forEach((key, value) - formData.add(key, value null ? : String.valueOf(value))); return restTemplate.postForObject(url, formData, String.class); }4. sa-token-rest-client整合 Spring RestClientRestClient 是 Spring Framework 6.1 引入的新一代同步 HTTP 客户端API 更加现代化推荐在 Spring Boot 3.2 / 4 中使用。!-- Sa-Token 整合 RestClient需 Spring Boot 3.2 / Spring Framework 6.1 -- dependency groupIdcn.dev33/groupId artifactIdsa-token-rest-client/artifactId version${sa.top.version}/version /dependencyGradle 参考implementation cn.dev33:sa-token-rest-client:${sa.top.version}实现类使用RestClient.create()POST 请求显式指定application/x-www-form-urlencodedprivate final RestClient restClient RestClient.create(); Override public String get(String url) { return restClient.get() .uri(url) .retrieve() .body(String.class); } Override public String postByFormData(String url, MapString, Object params) { MultiValueMapString, String formData new LinkedMultiValueMap(); params.forEach((key, value) - formData.add(key, value null ? : String.valueOf(value))); return restClient.post() .uri(url) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(formData) .retrieve() .body(String.class); }三、SPI 自动注入机制是如何工作的开发者只引入依赖、不写一行配置就能生效靠的是 Sa-Token 的插件 SPI 机制。以 Forest 插件为例其安装类 SaTokenPluginForForest 实现了SaTokenPlugin接口public class SaTokenPluginForForest implements SaTokenPlugin { Override public void install() { // 关闭 Forest 默认日志打印 ForestConfiguration.getDefaultConfiguration().setLogEnabled(false); // 设置 Forest 作为 Http 请求处理器 SaManager.setSaHttpTemplate(new SaHttpTemplateForForest()); } }当插件 jar 包出现在 classpath 时其META-INF/services下的 SPI 文件会被自动发现框架调用install()完成两件事关闭 Forest 自身的日志输出避免与 Sa-Token 日志体系重复通过SaManager.setSaHttpTemplate(...)注册全局 HTTP 处理器。对应地SaManager 中维护了一个volatile的SaHttpTemplate字段并在首次访问时惰性创建默认实现private volatile static SaHttpTemplate saHttpTemplate; public static void setSaHttpTemplate(SaHttpTemplate saHttpTemplate) { SaManager.saHttpTemplate saHttpTemplate; SaTokenEventCenter.doRegisterComponent(SaHttpTemplate, saHttpTemplate); } public static SaHttpTemplate getSaHttpTemplate() { if (saHttpTemplate null) { saHttpTemplate new SaHttpTemplateDefaultImpl(); } return saHttpTemplate; }默认实现 SaHttpTemplateDefaultImpl 的两个方法直接抛异常public static final String ERROR_MESSAGE HTTP 请求处理器未实现; Override public String get(String url) { throw new NotImplException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10004); }这解释了文档中的两点提醒未引入插件会报错任何 SSO 模式三 / 消息推送调用最终都会落到默认实现上并抛出「HTTP 请求处理器未实现」对外呈现为 30010 错误多插件并存时后加载者覆盖多个插件都会调用setSaHttpTemplate最终生效的是 SPI 加载顺序中的最后一个因此同一 classpath 下只应保留一个 HTTP 插件。四、选型建议不同运行环境推荐的插件不同官方文档给出了清晰的对照表运行环境推荐插件非 Spring / Solon 等sa-token-forest或sa-token-okhttpsSpring Boot 2或 Boot 3.0–3.1sa-token-rest-template或sa-token-forestSpring Boot 3.2 / 4优先sa-token-rest-client或sa-token-rest-template兼容旧代码选型时还需注意两条边界RestTemplate在 Spring Boot 4 中已标记为 deprecated但仍可使用RestClient需要 Spring Framework 6.1无法在 Spring Boot 2 或 Boot 3.0–3.1 中使用。决策建议若你的应用是纯 Spring 生态且希望少引入一个第三方 HTTP 库优先选sa-token-rest-template/sa-token-rest-client若项目处于 Solon、JFinal 等非 Spring 环境或需要保持 HTTP 客户端统一选sa-token-forest/sa-token-okhttps无论选择哪个插件务必保证 classpath 下只有一个HTTP 插件。五、使用场景SSO 模式三与消息推送HTTP 请求处理器主要服务于以下场景完整接入流程见对应文档SSO 模式三ticket 校验、单点注销、消息推送参考 sso-type3.md 与 message-push.mdSSO-Server 模式三Server 端同样需要配置 HTTP 请求处理器参考 sso-server.md。以 SSO 模式三为例Client 拿到 ticket 后调用SaSsoProcessor.instance.ssoLogin(...)框架内部通过SaHttpUtil.get(...)/SaHttpUtil.postByFormData(...)向 Server 的 ticket 校验接口发起请求当用户单点注销时Client 又会通过消息推送机制通知 Server 广播下线。若没有接入任何 HTTP 插件整个模式三流程将无法运行并在调用点抛出 30010 错误。六、自定义 Http 请求处理器除了使用官方插件Sa-Token 还提供了两种自定义方式便于接入公司内部已有的 HTTP 客户端或统一请求封装。方式一推荐引入官方插件SPI 自动注册只需添加上文任一插件依赖即可无需编写任何代码。这是最简单、也最不易出错的接入方式。方式二手动注册在应用启动阶段调用SaManager.setSaHttpTemplate(...)手动覆盖全局组件更完整的组件替换思路可参考 plugin-dev.md// 使用官方插件实现 SaManager.setSaHttpTemplate(new SaHttpTemplateForForest()); // 或自定义实现 SaHttpTemplate 接口 SaManager.setSaHttpTemplate(new SaHttpTemplate() { Override public String get(String url) { // 自定义 GET 逻辑 // ... } Override public String postByFormData(String url, MapString, Object params) { // 自定义 POST form-data 逻辑 // ... } });在 Spring Boot 环境中也可以通过注入SaHttpTemplate类型的 Bean 来覆盖默认实现参考 common-action.md。注意SaHttpTemplate接口只有get与postByFormData两个方法实现时需保证返回值为完整响应体文本String且 POST 参数以 form-data 形式提交否则可能影响 SSO ticket 校验、消息推送等功能的正常解析。七、错误码 30010 排查若运行时抛出「本地系统没有配置 http 请求处理器」说明当前 classpath 未引入任何 HTTP 插件且未手动设置SaHttpTemplate。从源码看该错误码定义于 SaSsoErrorCode.java/** 本地系统没有配置 http 请求处理器 */ int CODE_30010 30010;排查步骤确认是否已引入上文任一 HTTP 插件依赖sa-token-forest/sa-token-okhttps/sa-token-rest-template/sa-token-rest-client确认 classpath 中没有同时存在多个HTTP 插件多个插件会互相覆盖行为不可预期若确实不便引入插件检查是否在启动阶段通过SaManager.setSaHttpTemplate(...)或 Spring Bean 方式手动注册了实现若以上均正常可参考异常码表 exception-code.md 中关于sa-token-sso相关错误码的说明进一步定位。八、小结Sa-Token 通过SaHttpTemplate接口将内部 HTTP 调用与具体客户端实现解耦配合 SPI 自动注入机制让开发者只需引入一个依赖即可获得完整的 SSO 模式三、单点注销与消息推送能力接口极简仅get与postByFormData两个方法覆盖框架的全部 HTTP 需求接口定义四选一即可Forest / OkHttps 适配非 Spring 环境RestTemplate / RestClient 适配 Spring Boot 各版本按运行环境对照选型即可可替换官方插件之外支持手动setSaHttpTemplate与 Spring Bean 两种覆盖方式易排错30010 错误的唯一根因是没有配置任何 HTTP 请求处理器按上述排查清单即可快速解决。实际项目中SSO 模式三示例sa-token-demo下的各 SSO Client均以 Forest 为默认 HTTP 插件可作为参考实践直接对照使用。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表