Sa-Token SSO 自定义 API 路由:聚合式路由与拆分式路由的灵活改造指南

发布时间:2026/9/14 10:14:30
Sa-Token SSO 自定义 API 路由:聚合式路由与拆分式路由的灵活改造指南 Sa-Token SSO 自定义 API 路由聚合式路由与拆分式路由的灵活改造指南【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token导读默认情况下Sa-Token-SSO 模块内置一套固定不变的 API 路由如统一认证地址固定为/sso/auth所有 SSO 相关请求经由一个聚合入口转发。本篇指南以官方文档《SSO整合-自定义 API 路由》为主体结合sa-token-sso插件的真实源码ApiName、SaSsoServerProcessor、SaSsoClientProcessor与官方 Demo系统讲解两种自定义路由的方式——修改全局变量与拆分路由入口并延伸到 Server 端与 Client 端两套路由的完整对照。读完本文你将能够为 SSO 认证中心与应用端设计完全自主的 API 地址且不丢失任何内置功能。一、默认的聚合式路由入口在官方演示项目中SsoServerController.java 用一个RequestMapping(/sso/*)通配映射接住所有 SSO 请求再统一交给SaSsoServerProcessor.instance.dister()进行内部分发/** * Sa-Token-SSO Server端 Controller */ RestController public class SsoServerController { // SSO-Server端处理所有SSO相关请求 RequestMapping(/sso/*) public Object ssoRequest() { return SaSsoServerProcessor.instance.dister(); } // ... 其它代码 }这种写法集成简单但不够灵活认证中心地址被固化为http://{host}:{port}/sso/auth。如果你希望将这套地址改成/sso/auth2、/sso-user/auth甚至完全自定义就需要对本小节介绍的路由进行改造。二、SSO 模块的全部内置 API 路由一览SSO 模块所有 API 的名称与默认路径都集中定义在 ApiName.java自1.32.0版本起引入。这是一个可全局访问、字段公开的配置类共包含 11 个路由项字段名默认路径归属端作用ssoAuth/sso/authServer统一认证授权地址ssoDoLogin/sso/doLoginServerRestAPI 登录接口接收name、pwd参数ssoCheckTicket/sso/checkTicketServer校验 ticket、获取账号 idssoPushS/sso/pushSServer接收 Client 推送的消息ssoUserinfo/sso/userinfoServer获取用户资料userinfossoSignout/sso/signoutServer单点注销地址ssoLogin/sso/loginClient登录地址重定向到认证中心 / 按 ticket 登录ssoLogout/sso/logoutClient单点注销地址ssoIsLogin/sso/isLoginClient判断当前是否登录ssoLogoutCall/sso/logoutCallClient单点注销的回调地址模式三ssoPushC/sso/pushCClient接收 Server 推送的消息除此之外SSO 模块还把所有请求/响应参数名集中定义在 ParamName.java 中如redirect、ticket、back、mode、loginId、client、tokenValue、deviceId、name、pwd等。这两份 name 类共同决定了 SSO 通信的路由形状与参数形状是自定义改造的两大入口。三、方式一修改全局变量全局替换路由3.1 修改单个路由项既然ApiName是公开可变的配置对象最简单的做法就是在应用启动阶段直接改它的字段值。官方推荐在 SSO 配置方法中完成// 配置SSO相关参数 Autowired private void configSso(SaSsoServerTemplate ssoServerTemplate) { // 自定义API地址 SaSsoServerProcessor.instance.ssoServerTemplate.apiName.ssoAuth /sso/auth2; // ... }启动项目后统一认证地址就变成了http://{host}:{port}/sso/auth2。说明SaSsoServerProcessor.instance.ssoServerTemplate是 Server 端处理器的底层模板对象其apiName字段继承自公共模板 SaSsoTemplate.java 中的public ApiName apiName new ApiName()。因此直接对该字段赋值即可全局生效无需修改任何配置文件。3.2 批量加前缀addPrefix如果只想给全部路由统一加一段前缀ApiName提供了现成的addPrefix(String prefix)方法会为 11 个路由项一次性拼接前缀apiName.addPrefix(/sso-user); // 等价于把 ssoAuth 改为 /sso-user/sso/auth、ssoLogin 改为 /sso-user/sso/login ...该方法在源码中通过this.ssoAuth prefix this.ssoAuth;逐项完成拼接并返回对象自身以支持链式调用。3.3 批量替换前缀replacePrefix如果想去掉默认的/sso前缀、换成自己的路径风格则使用replacePrefix(String prefix)apiName.replacePrefix(/sso-user); // 等价于把 ssoAuth 改为 /sso-user/auth、ssoLogin 改为 /sso-user/login ...其内部实现使用String.replaceFirst(/sso, prefix)即只替换路径中第一处/sso前缀ApiName.java。两个批量方法都能让路由整体迁移只需一行代码尤其适合改造为/sso-user/*、/sso-admin/*这类带业务语义的前缀。3.4 替换整个 ApiName 对象SaSsoTemplate还提供了setApiName(ApiName apiName)方法允许传入一个完全自定义的ApiName子类或新实例来整体替换默认对象SaSsoTemplate.java。当你有大量字段需要定制时这是一种更整洁的做法。四、方式二拆分路由入口聚合式 → 拆分式文档将RequestMapping(/sso/*) dister()这种模式命名为聚合式路由一个方法接住所有请求由框架内部按路径分发。与之相对的拆分式路由则是把每一个 API 显式映射为独立的 Controller 方法逐个调用SaSsoServerProcessor.instance上对应的处理方法。4.1 Server 端拆分示例/** * Sa-Token-SSO Server端 Controller */ RestController public class SsoServerController { // SSO-Server统一认证地址 RequestMapping(/sso/auth) public Object ssoAuth() { return SaSsoServerProcessor.instance.ssoAuth(); } // SSO-ServerRestAPI 登录接口 RequestMapping(/sso/doLogin) public Object ssoDoLogin() { return SaSsoServerProcessor.instance.ssoDoLogin(); } // SSO-Server接收推送消息地址 RequestMapping(/sso/pushS) public Object ssoPushS() { return SaSsoServerProcessor.instance.ssoPushS(); } // SSO-Server单点注销 RequestMapping(/sso/signout) public Object ssoSignout() { return SaSsoServerProcessor.instance.ssoSignout(); } // ... 其它方法 }4.2 拆分式与聚合式为何等价从 SaSsoServerProcessor.java 的源码可以看到dister()的核心逻辑正是按apiName逐项匹配路径并转发到同名方法public Object dister() { SaRequest req SaHolder.getRequest(); ApiName apiName ssoServerTemplate.apiName; // sso-server授权地址 if(req.isPath(apiName.ssoAuth)) { return ssoAuth(); } // sso-serverRestAPI 登录接口 if(req.isPath(apiName.ssoDoLogin)) { return ssoDoLogin(); } // sso-server单点注销 if(req.isPath(apiName.ssoSignout)) { return ssoSignout(); } // sso-server接收推送消息 if(req.isPath(apiName.ssoPushS)) { return ssoPushS(); } // 默认返回 return SaSsoConsts.NOT_HANDLE; }也就是说聚合式路由本质上就是框架替你写好的if/else分发而拆分式路由则是你自己显式做 URL 到方法的映射。两者最终调用的是同一批处理逻辑ssoAuth()、ssoDoLogin()、ssoPushS()、ssoSignout()因此在功能上完全等价。拆分式路由的优势在于路由管控更细致每个 URL 独立映射可以叠加各自的拦截器、鉴权注解、参数校验或限流策略URL 自由度高可以把/sso/auth改成/login/authorize这类完全不同的路径不再依赖聚合入口调试更直观IDE 中每个入口方法都能直接跳转不必深入dister()的分发逻辑。4.3 Server 端拆分式路由的注意点如果仅修改了ApiName中的路径拆分式路由的RequestMapping必须与修改后的apiName路径保持一致否则框架内部如构建重定向地址、校验 ticket 时的回调地址计算会拿着apiName中的值去拼 URL而你的 Controller 却监听在旧路径上导致 404 或回调失败。ssoCheckTicket、ssoUserinfo等通过消息推送体系处理的接口本质上是ssoPushS收到消息后按消息类型分发的SaSsoMessageCheckTicketHandle、SaSsoMessageSignoutHandle在 SaSsoServerTemplate.java 构造时注册因此拆分入口时只需保留ssoPushS这一个消息接收口即可不必为每条消息单独建 URL。五、SSO-Client 端拆分路由入口示例Client 端的自定义思路与 Server 端完全一致默认聚合入口是SaSsoClientProcessor.instance.dister()其内部按apiName.ssoLogin、apiName.ssoLogout、apiName.ssoPushC、apiName.ssoLogoutCall分发SaSsoClientProcessor.java。拆分写法如下/** * Sa-Token-SSO Client端 Controller */ RestController public class SsoClientController { // SSO-Client登录地址 RequestMapping(/sso/login) public Object ssoLogin() { return SaSsoClientProcessor.instance.ssoLogin(); } // SSO-Client单点注销地址 RequestMapping(/sso/logout) public Object ssoLogout() { return SaSsoClientProcessor.instance.ssoLogout(); } // SSO-Client单点注销回调 RequestMapping(/sso/logoutCall) public Object ssoLogoutCall() { return SaSsoClientProcessor.instance.ssoLogoutCall(); } // SSO-Client接收消息推送地址 RequestMapping(/sso/pushC) public Object ssoPushC() { return SaSsoClientProcessor.instance.ssoPushC(); } // ... 其它方法 }5.1 各 Client 方法的职责还原拆分开之后每个方法的职责可以从源码中清楚地看到ssoLogin()无ticket参数时说明是 Client 端首次访问调用_goServerAuth()重定向到认证中心带ticket参数时说明是认证中心回跳调用_loginByTicket()按 ticket 完成登录SaSsoClientProcessor.java。ssoLogout()当isSlotrue开启单点注销时按模式三调用 Server 端注销接口实现全端下线否则返回NOT_HANDLE。ssoPushC()接收 Server 推送的消息如登录、注销广播校验参数签名后交给messageHolder处理。ssoLogoutCall()模式三下单点注销的回调Server 通知本端注销指定账号仅当配置regLogoutCalltrue时dister()才会放行到该方法。六、自定义时的配套参数与源码佐证6.1 路径与参数名是一套协议SSO 的 Server 端与 Client 端通过 URL 参数名互相通信因此两端路由必须协同修改。例如你把 Server 端ssoAuth改成了/sso/auth2那么 Client 端buildServerAuthUrl在拼接跳转认证中心的地址时读取的同样是apiName.ssoAuth——只要两端都基于同一个ApiName配置或在各自工程中做相同修改协议即可保持一致。这一点从 SaSsoClientProcessor.java 中_loginByTicket()同时引用apiName.ssoLogin与paramName.ticket可以印证路径与参数名是绑在一起参与流程的。6.2 模式二直连 Redis 校验 ticket的特殊提醒在模式二下Client 端校验 ticket 是直接调用 Server 端模板方法的SaSsoServerProcessor.instance.ssoServerTemplate.checkTicketParamAndDelete(...)见 SaSsoClientProcessor.java。源码注释明确指出如果 Server 端重写了SaSsoServerProcessor的部分方法而 Client 端没有按相同格式重写可能导致校验失败。这提醒我们自定义路由时尽量只改ApiName字段值而不要重写处理器的数据读写逻辑保持两端读写格式一致。6.3 版本前提ApiName、ParamName等名称类自1.32.0版本引入SaSsoServerProcessor/SaSsoClientProcessor处理器体系自1.38.0版本重构而来类注释since 1.38.0。使用本文方案前请确认项目引入的sa-token-sso插件版本不低于上述版本并参考仓库 sa-token-plugin/sa-token-sso 下的实际源码为准。七、快速验证你可以直接运行仓库中的官方 Demo 验证自定义效果启动 sa-token-demo-sso-server对应 SsoServerController.java 的聚合式写法按方式一修改configSso中的apiName.ssoAuth为/sso/auth2后重启访问http://{host}:{port}/sso/auth2确认原/sso/auth已失效、新地址可正常进入认证流程将 Controller 改为拆分式路由后逐一访问/sso/auth、/sso/doLogin、/sso/pushS、/sso/signout验证各入口独立可用配合 sa-token-demo-sso3-client 等 Client 端 Demo 走一遍跳转认证 → 回调登录 → 单点注销全链路确认自定义路径下消息推送与注销回调均正常。总结改全局变量直接修改ApiName的字段或使用addPrefix/replacePrefix批量调整适合整体迁移路径前缀、快速改造的场景拆分路由将聚合的dister()拆成独立RequestMapping方法适合精细管控单个 URL、叠加自定义拦截器的场景两种方式最终调用同一套处理器方法功能完全等价可放心选择核心要求是 Server 端与 Client 端路由协同、路径与apiName保持一致。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考