# Beacon SSO SDK (/docs/beacon-sso)
Beacon SSO SDK [#beacon-sso-sdk]
Beacon SSO SDK 为现代后端服务提供统一认证能力,支持多种语言技术栈,帮助快速集成 OAuth2 授权码流程、用户管理和商户服务。
选择你的技术栈 [#选择你的技术栈]
面向 Gin 框架的轻量级 OAuth2/SSO SDK,提供 OAuth2 授权码流程、gRPC 服务客户端和认证中间件。
基于 Spring Boot 3 的 OAuth2/SSO SDK,提供自动配置、Filter 认证、AOP 切面和可选 gRPC 服务。
核心能力 [#核心能力]
| 能力 | 说明 |
| ---------------- | ------------------------- |
| **OAuth2 授权码流程** | 完整的 State + PKCE 防护机制 |
| **gRPC 服务客户端** | 认证、用户、商户等核心服务 |
| **认证中间件/过滤器** | 开箱即用的 Token 验证 |
| **缓存策略** | 灵活的缓存方案(Redis / Caffeine) |
# AI 集成 (/docs/guide/ai-integration)
AI 集成 [#ai-集成]
本站原生支持 LLM(大语言模型)友好协议,你可以让 AI 助手直接读取文档内容,获得更精准的技术支持。
本文档站所有 LLM 可访问资源的根路径为:
```
https://beacon.api-fy.cn
```
后续所有路径示例均为**相对路径**,使用时请拼接上方根路径。
使用方式 [#使用方式]
方式一:文档索引 [#方式一文档索引]
访问 `/llms.txt` 获取所有文档页面的索引列表,然后按需请求单页内容。
```
https://beacon.api-fy.cn/llms.txt
```
方式二:单页 MDX 模式 [#方式二单页-mdx-模式]
每个文档页面都支持 MDX 原始内容获取,在路径后加 `.mdx` 前缀即可:
```
https://beacon.api-fy.cn/llms.mdx/docs/beacon-sso/go-sdk/quick-start
https://beacon.api-fy.cn/llms.mdx/docs/beacon-sso/java-sdk/quick-start
```
推荐方式(方式一 + 方式二结合) [#推荐方式方式一--方式二结合]
**先读索引,再按需拉取单页内容**——这是最高效的使用策略:
1. 访问 `/llms.txt` 获取所有页面的索引列表
2. 从索引中定位与问题相关的页面路径
3. 访问 `/llms.mdx/` 获取该页面的完整内容
4. 基于内容回答问题
这样可以避免一次性加载全量文档,让 AI 只获取真正需要的内容。
Agent Prompt 模板 [#agent-prompt-模板]
以下 prompt 可直接复制到任意支持网络请求的 AI Agent 中使用:
```markdown
请按以下步骤获取锋翎文档并回答我的问题:
1. 获取文档索引:https://beacon.api-fy.cn/llms.txt
2. 从索引中找到与我的问题相关的页面路径
3. 获取该页面内容:https://beacon.api-fy.cn/llms.mdx/<找到的路径>
4. 基于文档内容回答:[你的问题]
```
将上述 prompt 复制到 Claude、ChatGPT、Cursor 或其他支持网络请求的 AI 工具中,替换最后一行为你的具体问题,即可自动获取并分析文档内容。
相关链接 [#相关链接]
* [LLM 协议文件](/llms.txt) - 文档索引
* [完整文档](/llms-full.txt) - 所有内容合并
* [页面操作](./navigation) - 每页可复制 MDX 源码
参考资料 [#参考资料]
* **Beacon SSO 全局文档**: [https://beacon.api-fy.cn/llms.txt](https://beacon.api-fy.cn/llms.txt)
* **具体路径查询**: `https://beacon.api-fy.cn/llms.mdx/`
# 入门指南 (/docs/guide)
入门指南 [#入门指南]
欢迎使用锋翎文档!本指南将帮助你快速了解如何使用本站获取所需信息。
关于 Phalanx [#关于-phalanx]
Phalanx 是一套跨语言的后端服务组件库,旨在提供统一风格的 API 设计和开发体验。目前支持:
快速开始 [#快速开始]
选择你的语言 [#选择你的语言]
根据你的技术栈选择对应的文档:
* **Go 开发者**:前往 [Go 快速开始](../beacon-sso/go-sdk/quick-start) 了解如何在 Gin 项目中集成
* **Java 开发者**:前往 [Java 快速开始](../beacon-sso/java-sdk/quick-start) 了解如何在 Spring Boot 项目中集成
核心功能 [#核心功能]
Beacon SSO 在两种语言中提供了相似的核心功能:
| 功能 | 说明 |
| ------------- | ------------------ |
| **OAuth2 授权** | 完整的 OAuth2 授权码流程支持 |
| **gRPC 客户端** | 高效的服务间通信 |
| **缓存** | 灵活的缓存策略,降低鉴权开销 |
反馈与贡献 [#反馈与贡献]
如果你发现文档有误或有改进建议:
* **GitHub**:[xiaolfeng](https://github.com/xiaolfeng) 提交 Issue 或 PR
* **网站**:[筱锋的博客](https://www.x-lf.com) 留言
***
# 文档导航 (/docs/guide/navigation)
文档导航 [#文档导航]
了解如何高效浏览和使用锋翎文档站。
侧边栏 [#侧边栏]
左侧侧边栏提供了完整的文档目录结构,你可以:
* 点击展开/折叠分类
* 使用搜索功能快速定位(按 `Ctrl+K` 或 `Cmd+K`)
侧边栏特性 [#侧边栏特性]
| 特性 | 说明 |
| -------- | ---------------------------------- |
| **折叠记忆** | 侧边栏会记住你的折叠状态,下次访问时保持一致 |
| **快速跳转** | 使用键盘快捷键 `Ctrl+K` / `Cmd+K` 快速搜索并跳转 |
| **层级导航** | 支持多级目录结构,清晰展示文档层次 |
页面内导航 [#页面内导航]
每个文档页面右侧会显示当前页面的目录大纲(TOC),方便跳转到感兴趣的章节。
大纲特性 [#大纲特性]
* **自动生成**:根据标题层级自动生成
* **高亮当前**:滚动时自动高亮当前阅读的章节
* **点击跳转**:点击任意条目快速定位
页面操作 [#页面操作]
每个文档页面顶部提供了便捷操作按钮:
复制原始内容 [#复制原始内容]
点击复制按钮将当前页面的 MDX 源码复制到剪贴板,方便:
* 粘贴到 AI 对话中
* 保存到本地笔记
* 分享给他人
在 AI 平台打开 [#在-ai-平台打开]
一键跳转到 AI 平台并自动带上文档链接,支持:
* **ChatGPT**:跳转到 ChatGPT 并附带文档链接
* **Claude**:跳转到 Claude 并附带文档链接
* **其他平台**:更多 AI 平台持续添加中
如果你想在 AI 平台中讨论某个具体页面,直接点击「在 AI 平台打开」按钮,比手动复制链接更方便!
搜索功能 [#搜索功能]
全局搜索 [#全局搜索]
按 `Ctrl+K`(Windows/Linux)或 `Cmd+K`(macOS)打开搜索面板:
* 支持模糊搜索
* 搜索标题和内容
* 显示匹配结果预览
搜索技巧 [#搜索技巧]
| 技巧 | 示例 |
| ---- | ---------------- |
| 精确匹配 | `"BaseResponse"` |
| 模块搜索 | `beacon-sso` |
| 功能搜索 | `雪花算法` |
***
# 架构设计 (/docs/beacon-sso/go-sdk/architecture)
架构设计 [#架构设计]
Beacon SSO SDK 采用分层架构设计,与 bamboo-base-go 框架深度集成。
整体架构 [#整体架构]
依赖注入模式 [#依赖注入模式]
SDK 采用 bamboo-base-go 的 Register 依赖注入模式:
```go
// startup/startup.go
func NewStartupConfig(exclude ...string) []xRegNode.RegNodeList
```
该函数聚合了以下注册节点:
| 节点名称 | 说明 |
| ------------------ | -------------------------------- |
| `oAuthConfig` | OAuth2 核心配置(ClientID、Endpoint 等) |
| `oAuthRedirectURI` | OAuth2 重定向地址 |
| `ssoClient` | SsoClient gRPC 客户端 |
排除节点 [#排除节点]
你可以通过 `exclude` 参数排除特定节点:
```go
// 排除 gRPC 客户端(仅使用 OAuth2)
nodes := bSdkStartup.NewStartupConfig("ssoClient")
// 排除 OAuth 配置(使用自定义配置)
nodes := bSdkStartup.NewStartupConfig("oAuthConfig", "oAuthRedirectURI")
```
核心模块职责 [#核心模块职责]
| 模块 | 目录 | 职责 |
| -------------- | ------------- | --------- |
| **Startup** | `startup/` | 依赖注入节点定义 |
| **Route** | `route/` | Gin 路由注册 |
| **Handler** | `handler/` | HTTP 请求处理 |
| **Logic** | `logic/` | 业务逻辑封装 |
| **Client** | `client/` | gRPC 客户端 |
| **Repository** | `repository/` | 数据仓储层 |
| **Models** | `models/` | 数据模型定义 |
| **Middleware** | `middleware/` | Gin 中间件 |
| **Constant** | `constant/` | 常量定义 |
| **Utility** | `utility/` | 工具函数 |
两大子系统 [#两大子系统]
OAuth2 子系统 [#oauth2-子系统]
基于 `golang.org/x/oauth2` 扩展,提供:
* **授权码流程** - State + PKCE 防护
* **Token 管理** - Redis 缓存、自动刷新
* **业务能力** - Userinfo、Introspection(带缓存)
gRPC 子系统 [#grpc-子系统]
基于 `connectrpc.com/connect` 实现,提供:
| 服务 | 说明 | 认证要求 |
| ------------ | -------------- | ------------------- |
| **Public** | 公共服务(发送验证码) | 无 |
| **Auth** | 认证服务(注册/登录/改密) | App 凭证 |
| **User** | 用户服务(获取用户信息) | App 凭证 + User Token |
| **Merchant** | 商户服务(标签/公告) | App 凭证 |
与 bamboo-base-go 的集成 [#与-bamboo-base-go-的集成]
SDK 依赖 bamboo-base-go 的以下能力:
| 能力 | 用途 |
| --------------------- | ------------ |
| `xReg.Register` | 依赖注入容器 |
| `xCtxUtil.MustGetDB` | 从上下文获取数据库 |
| `xCtxUtil.MustGetRDB` | 从上下文获取 Redis |
| `xError` | 统一错误处理 |
| `xLog` | 结构化日志 |
| `xResult` | 统一响应格式 |
确保你的项目已正确配置 bamboo-base-go 框架。
# 环境变量配置 (/docs/beacon-sso/go-sdk/environment)
环境变量配置 [#环境变量配置]
Beacon SSO SDK 通过环境变量进行配置,分为 **OAuth2 配置** 和 **gRPC 配置** 两部分。
OAuth2 配置 [#oauth2-配置]
必填环境变量 [#必填环境变量]
| 变量名 | 说明 | 示例 |
| -------------------------------- | ----------------- | ------------------------------------------ |
| `SSO_CLIENT_ID` | OAuth2 客户端 ID | `my-app-client` |
| `SSO_CLIENT_SECRET` | OAuth2 客户端 Secret | `secret-key-xxx` |
| `SSO_REDIRECT_URI` | OAuth2 回调地址 | `http://localhost:8080/api/oauth/callback` |
| `SSO_ENDPOINT_AUTH_URI` | 授权端点 | `https://sso.example.com/oauth/authorize` |
| `SSO_ENDPOINT_TOKEN_URI` | 令牌端点 | `https://sso.example.com/oauth/token` |
| `SSO_ENDPOINT_USERINFO_URI` | 用户信息端点 | `https://sso.example.com/oauth/userinfo` |
| `SSO_ENDPOINT_INTROSPECTION_URI` | 令牌自省端点 | `https://sso.example.com/oauth/introspect` |
| `SSO_ENDPOINT_REVOCATION_URI` | 令牌注销端点 | `https://sso.example.com/oauth/revoke` |
可选环境变量 [#可选环境变量]
| 变量名 | 说明 | 默认值 |
| -------------------- | ------ | ----------- |
| `SSO_WELL_KNOWN_URI` | 自动发现端点 | 空(需手动配置各端点) |
| `SSO_BUSINESS_CACHE` | 业务缓存开关 | `false` |
gRPC 配置 [#grpc-配置]
必填环境变量 [#必填环境变量-1]
| 变量名 | 说明 | 示例 |
| --------------- | --------- | ----------------- |
| `SSO_GRPC_HOST` | gRPC 主机地址 | `sso.example.com` |
| `SSO_GRPC_PORT` | gRPC 端口 | `5566` |
Well-Known 自动发现 [#well-known-自动发现]
如果你配置了 `SSO_WELL_KNOWN_URI`,SDK 会自动从该端点获取以下配置:
* `authorization_endpoint`
* `token_endpoint`
* `userinfo_endpoint`
* `introspection_endpoint`
* `revocation_endpoint`
配置 `SSO_WELL_KNOWN_URI` 后,可以省略所有 `SSO_ENDPOINT_*` 环境变量。
配置示例 [#配置示例]
.env 文件 [#env-文件]
```bash
# OAuth2 配置
SSO_CLIENT_ID=my-app-client
SSO_CLIENT_SECRET=secret-key-xxx
SSO_REDIRECT_URI=http://localhost:8080/api/oauth/callback
SSO_ENDPOINT_AUTH_URI=https://sso.example.com/oauth/authorize
SSO_ENDPOINT_TOKEN_URI=https://sso.example.com/oauth/token
SSO_ENDPOINT_USERINFO_URI=https://sso.example.com/oauth/userinfo
SSO_ENDPOINT_INTROSPECTION_URI=https://sso.example.com/oauth/introspect
SSO_ENDPOINT_REVOCATION_URI=https://sso.example.com/oauth/revoke
# gRPC 配置
SSO_GRPC_HOST=sso.example.com
SSO_GRPC_PORT=5566
# 可选配置
SSO_BUSINESS_CACHE=true
```
使用 Well-Known 自动发现 [#使用-well-known-自动发现]
```bash
# 使用自动发现时,只需配置以下变量
SSO_CLIENT_ID=my-app-client
SSO_CLIENT_SECRET=secret-key-xxx
SSO_REDIRECT_URI=http://localhost:8080/api/oauth/callback
SSO_WELL_KNOWN_URI=https://sso.example.com/.well-known/openid-configuration
# gRPC 配置仍需手动填写
SSO_GRPC_HOST=sso.example.com
SSO_GRPC_PORT=5566
```
业务缓存说明 [#业务缓存说明]
`SSO_BUSINESS_CACHE` 控制以下业务逻辑的 Redis 缓存:
| 功能 | 缓存键模板 | TTL |
| ------------- | --------------------------------------------- | ------------------------- |
| Userinfo | `oauth:biz:userinfo:{accessToken}` | 30 秒 |
| Introspection | `oauth:biz:introspection:{tokenType}:{token}` | 动态(取 min(expiresIn, 30s)) |
开启业务缓存后,用户信息变更可能会有最多 30 秒的延迟。
# Go SDK (/docs/beacon-sso/go-sdk)
Go SDK [#go-sdk]
面向 Gin 项目的轻量级 OAuth2/SSO SDK,提供统一登录、用户管理和商户服务能力。
核心特性 [#核心特性]
* **OAuth2 授权码流程** - 完整的 State + PKCE 防护机制
* **Token 缓存管理** - 基于 Redis 的 Token 自动缓存与刷新
* **gRPC 服务客户端** - 四大服务(Public / Auth / User / Merchant)
* **认证中间件** - 开箱即用的 Token 验证中间件
* **灵活的依赖注入** - 与 bamboo-base-go 框架无缝集成
子系统概览 [#子系统概览]
| 子系统 | 说明 | 协议 |
| ------------------ | ---------- | ----------------- |
| [OAuth2](./oauth2) | 登录/回调/登出流程 | HTTP REST + Redis |
| [gRPC](./grpc) | 用户/认证/商户服务 | Connect-RPC |
版本信息 [#版本信息]
* 当前版本: v1.0.0
* Go 版本: 1.25.3+
* 依赖框架: bamboo-base-go
快速开始 [#快速开始]
5 分钟快速集成,请参考 [快速开始](./quick-start)。
# 快速开始 (/docs/beacon-sso/go-sdk/quick-start)
快速开始 [#快速开始]
本指南将帮助你在 5 分钟内完成 Beacon SSO SDK 的集成。
安装 [#安装]
```bash
go get github.com/phalanx-labs/beacon-sso-sdk
```
完整示例 [#完整示例]
以下是一个完整的 Gin 服务示例,集成了 OAuth2 登录和 gRPC 服务:
```go
package main
import (
"context"
xConsts "github.com/bamboo-services/bamboo-base-go/defined/context"
xReg "github.com/bamboo-services/bamboo-base-go/major/register"
xRegNode "github.com/bamboo-services/bamboo-base-go/major/register/node"
xResult "github.com/bamboo-services/bamboo-base-go/major/result"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
bSdkRoute "github.com/phalanx-labs/beacon-sso-sdk/route"
bSdkStartup "github.com/phalanx-labs/beacon-sso-sdk/startup"
"gorm.io/gorm"
)
func main() {
// 1) 初始化注册节点(数据库、Redis + SDK 配置)
nodes := []xRegNode.RegNodeList{
{Key: xConsts.DatabaseKey, Node: initDatabase},
{Key: xConsts.RedisClientKey, Node: initRedis},
}
nodes = append(nodes, bSdkStartup.NewStartupConfig()...)
reg := xReg.Register(context.Background(), nodes)
// 2) 注册业务路由
reg.Serve.GET("/api/status", func(c *gin.Context) {
xResult.SuccessHasData(c, "服务正常", gin.H{
"status": "running",
})
})
// 3) 挂载 SDK 路由
sdkRoute := bSdkRoute.NewRoute(reg.Init.Ctx)
// OAuth2 路由(登录/回调/登出)
sdkRoute.OAuthRouter(reg.Serve.Group("/api"))
// 账户路由(注册/密码登录/刷新令牌)
sdkRoute.AccountRouter(reg.Serve.Group("/api"))
// 用户路由(获取用户信息)
sdkRoute.UserRouter(reg.Serve.Group("/api"))
// 4) 启动服务
_ = reg.Serve.Run(":8080")
}
// 数据库初始化节点
func initDatabase(ctx context.Context) (any, error) {
// TODO: 替换为你的数据库初始化逻辑
var db *gorm.DB
return db, nil
}
// Redis 初始化节点
func initRedis(ctx context.Context) (any, error) {
// TODO: 替换为你的 Redis 初始化逻辑
var rdb *redis.Client
return rdb, nil
}
```
默认路由 [#默认路由]
SDK 会自动注册以下路由:
OAuth2 路由 [#oauth2-路由]
| 方法 | 路径 | 说明 |
| ---- | --------------------- | ------------------------ |
| GET | `/api/oauth/login` | 302 重定向到 SSO 授权页面 |
| GET | `/api/oauth/callback` | OAuth2 回调,用 code 换 token |
| POST | `/api/oauth/logout` | 注销 token |
账户路由 [#账户路由]
| 方法 | 路径 | 说明 |
| ---- | ------------------------------ | ---- |
| POST | `/api/account/register/email` | 邮箱注册 |
| POST | `/api/account/login/password` | 密码登录 |
| POST | `/api/account/token/refresh` | 刷新令牌 |
| POST | `/api/account/password/change` | 修改密码 |
| POST | `/api/account/token/revoke` | 注销令牌 |
用户路由 [#用户路由]
| 方法 | 路径 | 说明 |
| --- | -------------------- | ------------ |
| GET | `/api/user/userinfo` | 获取当前用户信息 |
| GET | `/api/user/by-id` | 根据 ID 获取用户信息 |
环境变量配置 [#环境变量配置]
在运行前,请确保配置以下环境变量:
```bash
# 必填 - OAuth2 配置
SSO_CLIENT_ID=your-client-id
SSO_CLIENT_SECRET=your-client-secret
SSO_REDIRECT_URI=http://localhost:8080/api/oauth/callback
SSO_ENDPOINT_AUTH_URI=https://sso.example.com/oauth/authorize
SSO_ENDPOINT_TOKEN_URI=https://sso.example.com/oauth/token
SSO_ENDPOINT_USERINFO_URI=https://sso.example.com/oauth/userinfo
SSO_ENDPOINT_INTROSPECTION_URI=https://sso.example.com/oauth/introspect
SSO_ENDPOINT_REVOCATION_URI=https://sso.example.com/oauth/revoke
# 必填 - gRPC 配置
SSO_GRPC_HOST=sso.example.com
SSO_GRPC_PORT=5566
```
完整的环境变量说明请参考 [环境变量配置](./environment)。
验证安装 [#验证安装]
启动服务后,访问以下地址测试:
1. **登录跳转**: `GET http://localhost:8080/api/oauth/login`
2. **服务状态**: `GET http://localhost:8080/api/status`
下一步 [#下一步]
* [环境变量配置](./environment) - 了解所有可配置项
* [架构设计](./architecture) - 理解 SDK 的整体架构
* [OAuth2 子系统](./oauth2) - 深入了解授权流程
* [gRPC 服务](./grpc) - 使用 gRPC 客户端
# 架构设计 (/docs/beacon-sso/java-sdk/architecture)
架构设计 [#架构设计]
Beacon SSO Java SDK 采用多模块分层架构设计,基于 Spring Boot 自动配置机制实现零侵入集成。
整体架构 [#整体架构]
多模块结构 [#多模块结构]
SDK 采用 Maven 多模块设计:
| 模块 | Artifact | 说明 |
| ----------------------------- | --------------------------- | ------------------------------------------------- |
| **bamboo-sso-base** | `bamboo-sso-base` | 核心模块:属性配置、gRPC/HTTP 客户端、数据模型、缓存、异常 |
| **bamboo-sso-sdk-springboot** | `bamboo-sso-sdk-springboot` | Spring Boot Starter:自动配置、Filter、Controller、AOP 切面 |
Spring Boot 自动配置 [#spring-boot-自动配置]
SDK 通过 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports` 注册自动配置类:
| 配置类 | 条件 | 注册的 Bean |
| -------------------------------------- | ------------------------------ | ---------------------------------- |
| `AutoConfiguration` | `beacon.sso.enabled=true`(默认) | WebClient、SsoApi、CacheManager |
| `BeaconSsoSpringBootAutoConfiguration` | Servlet Web 应用 | BeaconSsoFilter、Controllers、AOP 切面 |
| `GrpcConfiguration` | `beacon.sso.grpc.enabled=true` | ManagedChannel |
你只需引入 `bamboo-sso-sdk-springboot` 依赖并在 `application.yml` 中配置属性,所有 Bean 会自动注册到 Spring 容器中。
SsoApi 统一入口 [#ssoapi-统一入口]
`SsoApi` 是 SDK 的核心 Facade,通过 Spring IoC 容器注入使用:
```java
@Autowired
private SsoApi ssoApi;
// 账户服务(gRPC)
ssoApi.account().registerByEmail(request);
ssoApi.account().passwordLogin(request);
// 用户服务(gRPC 优先,HTTP 回退)
ssoApi.user().getCurrentUser(accessToken, request);
// 商户服务(gRPC)
ssoApi.merchant().getMerchantTags();
// 公共服务(gRPC)
ssoApi.pub().sendRegisterEmailCode(request);
```
| 子 API | 说明 | 传输方式 |
| ------------------- | -------------- | --------------- |
| `ssoApi.account()` | 账户管理(注册/登录/改密) | gRPC |
| `ssoApi.user()` | 用户信息查询 | gRPC 优先,HTTP 回退 |
| `ssoApi.merchant()` | 商户标签/公告 | gRPC |
| `ssoApi.pub()` | 公共服务(验证码) | gRPC |
双传输架构 [#双传输架构]
SDK 支持 HTTP 和 gRPC 两种传输方式:
| 功能 | HTTP | gRPC | 说明 |
| ----------- | ---- | ------ | ------------ |
| OAuth2 登录流程 | 默认 | - | 始终使用 HTTP |
| Token 自省 | 默认 | - | 始终使用 HTTP |
| 获取当前用户 | 回退 | 优先 | gRPC 启用时优先使用 |
| 按 ID 获取用户 | - | 仅 gRPC | 需启用 gRPC |
| 邮箱注册/密码登录 | - | 仅 gRPC | 需启用 gRPC |
| 商户标签/公告 | - | 仅 gRPC | 需启用 gRPC |
OAuth2 授权流程 [#oauth2-授权流程]
# 配置参考 (/docs/beacon-sso/java-sdk/configuration)
配置参考 [#配置参考]
Beacon SSO Java SDK 通过 `application.yml` / `application.properties` 中的 `beacon.sso.*` 属性进行配置。
核心配置 [#核心配置]
必填配置 [#必填配置]
| 属性 | 说明 | 示例 |
| -------------------------- | ----------------- | -------------------------------------- |
| `beacon.sso.base-url` | SSO 服务器基础 URL | `https://sso.example.com` |
| `beacon.sso.client-id` | OAuth2 客户端 ID | `my-app-client` |
| `beacon.sso.client-secret` | OAuth2 客户端 Secret | `secret-key-xxx` |
| `beacon.sso.redirect-uri` | OAuth2 回调地址 | `http://localhost:8080/oauth/callback` |
可选配置 [#可选配置]
| 属性 | 说明 | 默认值 |
| --------------------------- | ------------------------ | ------ |
| `beacon.sso.enabled` | SDK 总开关 | `true` |
| `beacon.sso.exclude-urls` | Filter 排除路径(Ant 风格匹配) | 空 |
| `beacon.sso.well-known-uri` | OIDC Well-Known 自动发现 URI | 空 |
OAuth2 端点配置 [#oauth2-端点配置]
SDK 内置了默认的端点路径,通常无需手动配置:
| 属性 | 默认值 | 说明 |
| ---------------------------------------- | ------------------- | ------ |
| `beacon.sso.endpoints.auth-uri` | `/oauth/authorize` | 授权端点 |
| `beacon.sso.endpoints.token-uri` | `/oauth/token` | 令牌端点 |
| `beacon.sso.endpoints.userinfo-uri` | `/oauth/userinfo` | 用户信息端点 |
| `beacon.sso.endpoints.introspection-uri` | `/oauth/introspect` | 令牌自省端点 |
| `beacon.sso.endpoints.revocation-uri` | `/oauth/revoke` | 令牌注销端点 |
以上端点路径会与 `beacon.sso.base-url` 拼接成完整 URL。例如 `base-url` 为 `https://sso.example.com` 时,Token 端点为 `https://sso.example.com/oauth/token`。
路由前缀配置 [#路由前缀配置]
SDK 自动注册的 Controller 路径前缀均可自定义:
| 属性 | 默认值 | 说明 |
| -------------------------- | ----------- | ----------- |
| `beacon.sso.oauth-path` | `/oauth` | OAuth2 路由前缀 |
| `beacon.sso.account-path` | `/account` | 账户路由前缀 |
| `beacon.sso.user-path` | `/user` | 用户路由前缀 |
| `beacon.sso.public-path` | `/public` | 公共路由前缀 |
| `beacon.sso.merchant-path` | `/merchant` | 商户路由前缀 |
例如将 OAuth 路由前缀改为 `/sso`:
```yaml
beacon:
sso:
oauth-path: /sso
```
则登录路由变为 `/sso/login`,回调路由变为 `/sso/callback`。
gRPC 配置 [#grpc-配置]
gRPC 默认**关闭**,需要手动启用:
必填配置(启用 gRPC 时) [#必填配置启用-grpc-时]
| 属性 | 说明 | 示例 |
| -------------------------------- | ---------- | ----------------- |
| `beacon.sso.grpc.enabled` | 启用 gRPC | `true` |
| `beacon.sso.grpc.host` | gRPC 服务器地址 | `sso.example.com` |
| `beacon.sso.grpc.port` | gRPC 服务器端口 | `5566` |
| `beacon.sso.grpc.app-access-id` | 应用凭证 ID | `app-xxx` |
| `beacon.sso.grpc.app-secret-key` | 应用凭证密钥 | `secret-xxx` |
Well-Known 自动发现 [#well-known-自动发现]
如果你配置了 `beacon.sso.well-known-uri`,SDK 会在启动时自动从该端点获取 OAuth2 端点配置:
* `authorization_endpoint`
* `token_endpoint`
* `userinfo_endpoint`
* `introspection_endpoint`
* `revocation_endpoint`
配置 `well-known-uri` 后,无需手动配置 `beacon.sso.endpoints.*` 相关属性。自动发现**仅覆盖**仍为默认值的端点路径。
完整配置示例 [#完整配置示例]
基础配置(仅 OAuth2) [#基础配置仅-oauth2]
```yaml
beacon:
sso:
base-url: https://sso.example.com
client-id: my-app-client
client-secret: secret-key-xxx
redirect-uri: http://localhost:8080/oauth/callback
exclude-urls:
- /api/public/**
- /actuator/**
```
完整配置(OAuth2 + gRPC) [#完整配置oauth2--grpc]
```yaml
beacon:
sso:
base-url: https://sso.example.com
client-id: my-app-client
client-secret: secret-key-xxx
redirect-uri: http://localhost:8080/oauth/callback
exclude-urls:
- /api/public/**
grpc:
enabled: true
host: sso.example.com
port: 5566
app-access-id: app-xxx
app-secret-key: secret-xxx
```
使用 Well-Known 自动发现 [#使用-well-known-自动发现]
```yaml
beacon:
sso:
base-url: https://sso.example.com
client-id: my-app-client
client-secret: secret-key-xxx
redirect-uri: http://localhost:8080/oauth/callback
well-known-uri: https://sso.example.com/.well-known/openid-configuration
grpc:
enabled: true
host: sso.example.com
port: 5566
app-access-id: app-xxx
app-secret-key: secret-xxx
```
# Java SDK (/docs/beacon-sso/java-sdk)
Java SDK [#java-sdk]
基于 Spring Boot 3 的轻量级 OAuth2/SSO SDK,提供统一登录、用户管理和商户服务能力。
核心特性 [#核心特性]
* **OAuth2 授权码流程** - 完整的 State + PKCE (S256) 防护机制
* **Spring Boot 自动配置** - 引入 Starter 即可,零配置启动
* **双传输架构** - HTTP(默认)+ 可选 gRPC 服务
* **Filter + AOP 认证** - `BeaconSsoFilter` 过滤器 + `@InjectData` / `@PermissionVerify` 注解
* **Caffeine 缓存** - 基于 Caffeine 的高性能内存缓存
子系统概览 [#子系统概览]
| 子系统 | 说明 | 协议 |
| ------------------ | ---------- | -------------------- |
| [OAuth2](./oauth2) | 登录/回调/登出流程 | HTTP REST + Caffeine |
| [gRPC](./grpc) | 用户/认证/商户服务 | gRPC(可选) |
版本信息 [#版本信息]
* 当前版本: 0.0.1-SNAPSHOT
* Java 版本: 17+
* Spring Boot: 3.5.11
* Maven 坐标: `com.frontleaves.phalanx.beacon.sso:bamboo-sso-sdk-springboot`
快速开始 [#快速开始]
5 分钟快速集成,请参考 [快速开始](./quick-start)。
# 快速开始 (/docs/beacon-sso/java-sdk/quick-start)
快速开始 [#快速开始]
本指南将帮助你在 5 分钟内完成 Beacon SSO Java SDK 的集成。
添加依赖 [#添加依赖]
在 `pom.xml` 中添加 SDK 依赖:
```xml
com.frontleaves.phalanx.beacon.sso
bamboo-sso-sdk-springboot
0.0.1-SNAPSHOT
```
配置 [#配置]
在 `application.yml` 中添加最小配置:
```yaml
beacon:
sso:
base-url: https://sso.example.com
client-id: your-client-id
client-secret: your-client-secret
redirect-uri: http://localhost:8080/oauth/callback
```
SDK 通过 Spring Boot 自动配置机制,会在应用启动时自动注册 Filter、Controller 和 AOP 切面。你无需编写任何额外代码即可使用 OAuth2 登录流程。
启动应用 [#启动应用]
添加依赖和配置后,直接启动你的 Spring Boot 应用即可:
```java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
使用示例 [#使用示例]
获取当前用户信息 [#获取当前用户信息]
SDK 自动注册了 `BeaconSsoFilter`,所有请求(排除 `beacon.sso.exclude-urls` 配置的路径)都会进行 Token 验证。在 Controller 中通过 `@InjectData` 注解获取用户信息:
```java
@RestController
@RequestMapping("/api")
public class DemoController {
@GetMapping("/profile")
public BaseResponse getProfile(
@InjectData("sub") String userId) {
// 直接使用注入的 userId
return BaseResponse.success("获取成功", null);
}
}
```
注入完整 Token 信息 [#注入完整-token-信息]
```java
@GetMapping("/token-info")
public BaseResponse getTokenInfo(
@InjectData IntrospectResult introspectResult) {
return BaseResponse.success("获取成功", introspectResult);
}
```
默认路由 [#默认路由]
SDK 自动注册以下路由(路径前缀可配置):
OAuth2 路由 [#oauth2-路由]
| 方法 | 路径 | 说明 |
| --- | ----------------- | ------------------------ |
| GET | `/oauth/login` | 302 重定向到 SSO 授权页面 |
| GET | `/oauth/callback` | OAuth2 回调,用 code 换 token |
| GET | `/oauth/logout` | 注销并清除 Session |
| GET | `/oauth/status` | 获取当前认证状态 |
账户路由 [#账户路由]
| 方法 | 路径 | 说明 |
| ---- | -------------------------- | -------- |
| POST | `/account/register/email` | 邮箱注册 |
| POST | `/account/login/password` | 密码登录 |
| POST | `/account/password/change` | 修改密码 |
| POST | `/account/logout` | 注销 Token |
用户路由(需 gRPC) [#用户路由需-grpc]
| 方法 | 路径 | 说明 |
| --- | ---------------- | ------------ |
| GET | `/user/userinfo` | 获取当前用户信息 |
| GET | `/user/{userId}` | 根据 ID 获取用户详情 |
账户路由和用户路由依赖 gRPC 服务,需额外配置 `beacon.sso.grpc.enabled=true` 及相关连接参数。
验证安装 [#验证安装]
启动服务后,访问以下地址测试:
1. **登录跳转**: `GET http://localhost:8080/oauth/login`
2. **认证状态**: `GET http://localhost:8080/oauth/status`
下一步 [#下一步]
* [配置参考](./configuration) - 了解所有可配置项
* [架构设计](./architecture) - 理解 SDK 的整体架构
* [OAuth2 子系统](./oauth2) - 深入了解授权流程
* [gRPC 服务](./grpc) - 启用和使用 gRPC 客户端
# 缓存策略 (/docs/beacon-sso/go-sdk/advanced/cache)
缓存策略 [#缓存策略]
SDK 使用 Redis 进行多层次缓存,以提升性能和减少对 SSO Server 的请求。
缓存层级 [#缓存层级]
缓存详情 [#缓存详情]
OAuth2 核心缓存 [#oauth2-核心缓存]
| 缓存类型 | Key 模板 | TTL | 可控 |
| ---------- | --------------------------- | ----- | -- |
| State/PKCE | `oauth:state:{state}` | 15 分钟 | 否 |
| Token | `oauth:token:{accessToken}` | 30 天 | 否 |
**说明:** OAuth2 核心缓存始终启用,无法关闭。
业务缓存 [#业务缓存]
| 缓存类型 | Key 模板 | TTL | 可控 |
| ------------- | --------------------------------------------- | ---- | -- |
| Userinfo | `oauth:biz:userinfo:{accessToken}` | 30 秒 | 是 |
| Introspection | `oauth:biz:introspection:{tokenType}:{token}` | 动态 | 是 |
**动态 TTL 计算:**
Introspection 的 TTL 取 `min(expiresIn, 30s)`,确保不会缓存已过期的结果。
业务缓存开关 [#业务缓存开关]
通过 `SSO_BUSINESS_CACHE` 环境变量控制:
```bash
# 开启业务缓存(默认关闭)
SSO_BUSINESS_CACHE=true
```
开启缓存的影响 [#开启缓存的影响]
| 影响 | 说明 |
| -------- | ------------------------ |
| **性能提升** | 减少对 SSO Server 的 HTTP 请求 |
| **数据延迟** | 用户信息变更最多延迟 30 秒 |
| **内存占用** | Redis 占用增加 |
开启业务缓存后,用户信息变更(如修改昵称)可能会有最多 30 秒的延迟。如果你的应用需要实时的用户信息,请保持缓存关闭。
使用 BusinessLogic [#使用-businesslogic]
BusinessLogic 提供 Userinfo 和 Introspection 能力,缓存逻辑已内置:
```go
import bSdkLogic "github.com/phalanx-labs/beacon-sso-sdk/logic"
func main() {
ctx := context.Background()
businessLogic := bSdkLogic.NewBusiness(ctx)
// 获取用户信息(带缓存)
userinfo, err := businessLogic.Userinfo(ctx, accessToken)
if err != nil {
panic(err)
}
fmt.Printf("用户: %s\n", userinfo.Nickname)
// 查询令牌状态(带缓存)
intro, err := businessLogic.Introspection(ctx, "access_token", accessToken)
if err != nil {
panic(err)
}
fmt.Printf("令牌状态: %v\n", intro.Active)
fmt.Printf("过期时间: %s\n", intro.Expiry)
}
```
手动清理缓存 [#手动清理缓存]
如果需要在用户信息变更后立即清理缓存:
```go
// 目前需要直接操作 Redis
rdb.Del(ctx, "oauth:biz:userinfo:"+accessToken)
rdb.Del(ctx, "oauth:biz:introspection:access_token:"+accessToken)
```
缓存模型 [#缓存模型]
CacheOAuth [#cacheoauth]
```go
type CacheOAuth struct {
State string // 随机状态码
Verifier string // PKCE 验证器
}
```
CacheOAuthToken [#cacheoauthtoken]
```go
type CacheOAuthToken struct {
AccessToken string // 访问令牌
TokenType string // 令牌类型
RefreshToken string // 刷新令牌
Expiry string // 过期时间(RFC3339)
}
```
OAuthUserinfo [#oauthuserinfo]
```go
type OAuthUserinfo struct {
Sub string // 用户唯一标识
Nickname string // 昵称
PreferredUsername string // 首选用户名
Email string // 邮箱
Phone string // 手机号
Raw map[string]any // 原始响应数据
}
```
OAuthIntrospection [#oauthintrospection]
```go
type OAuthIntrospection struct {
Active bool // 令牌是否有效
TokenType string // 令牌类型
Exp int64 // 过期时间戳(Unix)
Expiry string // 过期时间(RFC3339)
ExpiresIn int64 // 剩余有效时间(秒)
IsExpired bool // 是否已过期
Raw map[string]any // 原始响应数据
}
```
# 高级话题 (/docs/beacon-sso/go-sdk/advanced)
高级话题 [#高级话题]
本章节介绍 SDK 的高级配置和定制选项。
子文档 [#子文档]
了解 SDK 的 Redis 缓存机制和配置选项
自定义初始化 [#自定义初始化]
排除特定节点 [#排除特定节点]
你可以通过 `exclude` 参数排除不需要的初始化节点:
```go
// 仅使用 OAuth2,排除 gRPC 客户端
nodes := bSdkStartup.NewStartupConfig("ssoClient")
// 排除 OAuth 配置(使用自定义 OAuth 配置)
nodes := bSdkStartup.NewStartupConfig("oAuthConfig", "oAuthRedirectURI")
```
可排除的节点 [#可排除的节点]
| 节点名称 | 说明 |
| ------------------ | ------------------ |
| `oAuthConfig` | OAuth2 核心配置 |
| `oAuthRedirectURI` | OAuth2 重定向地址 |
| `ssoClient` | SsoClient gRPC 客户端 |
独立使用 Logic 层 [#独立使用-logic-层]
你可以直接实例化 Logic 层,而不使用 SDK 提供的路由:
```go
import bSdkLogic "github.com/phalanx-labs/beacon-sso-sdk/logic"
func customHandler(c *gin.Context) {
ctx := c.Request.Context()
// 使用 OAuthLogic
oauthLogic := bSdkLogic.NewOAuth(ctx)
// 使用 AuthLogic
authLogic := bSdkLogic.NewAuth(ctx)
// 使用 UserLogic
userLogic := bSdkLogic.NewUser(ctx)
// 使用 BusinessLogic
businessLogic := bSdkLogic.NewBusiness(ctx)
}
```
直接使用 gRPC 客户端 [#直接使用-grpc-客户端]
如果不需要 OAuth2 功能,可以只使用 gRPC 客户端:
```go
import bSdkClient "github.com/phalanx-labs/beacon-sso-sdk/client"
func main() {
// 仅创建 gRPC 客户端
client := bSdkClient.NewClient(
bSdkClient.WithConnect("sso.example.com", "5566"),
bSdkClient.WithAppAccess("app-id", "app-secret"),
)
// 使用 gRPC 服务
client.Auth.PasswordLogin(ctx, req)
client.User.GetCurrentUser(ctx, token)
client.Merchant.GetMerchantTags(ctx, req)
}
```
# 错误码 (/docs/beacon-sso/go-sdk/api/errors)
错误码 [#错误码]
SDK 使用 bamboo-base-go 的统一错误处理体系。
错误结构 [#错误结构]
所有错误都遵循统一的结构:
```go
type Error struct {
ErrorCode ErrorCode // 错误码
ErrorMessage string // 错误消息
Data any // 附加数据
}
```
常见错误码 [#常见错误码]
参数错误 [#参数错误]
| 错误码 | 说明 | HTTP 状态码 |
| ---------------- | ------ | -------- |
| `ParameterEmpty` | 必填参数为空 | 400 |
| `ParameterError` | 参数格式错误 | 400 |
认证错误 [#认证错误]
| 错误码 | 说明 | HTTP 状态码 |
| -------------- | ------------- | -------- |
| `Unauthorized` | 未登录或 Token 无效 | 401 |
| `TokenExpired` | Token 已过期 | 401 |
资源错误 [#资源错误]
| 错误码 | 说明 | HTTP 状态码 |
| ---------- | ----- | -------- |
| `NotExist` | 资源不存在 | 404 |
操作错误 [#操作错误]
| 错误码 | 说明 | HTTP 状态码 |
| ----------------- | ---- | -------- |
| `OperationFailed` | 操作失败 | 500 |
错误响应示例 [#错误响应示例]
参数为空 [#参数为空]
```json
{
"code": 400,
"message": "状态为空",
"data": null
}
```
Token 过期 [#token-过期]
```json
{
"code": 401,
"message": "访问令牌已过期",
"data": null
}
```
未登录 [#未登录]
```json
{
"code": 401,
"message": "未登录",
"data": null
}
```
错误处理 [#错误处理]
在 Handler 中 [#在-handler-中]
```go
import xResult "github.com/bamboo-services/bamboo-base-go/major/result"
func handler(c *gin.Context) {
result, err := someLogic.DoSomething(ctx)
if err != nil {
xResult.AbortError(c, err.ErrorCode, err.ErrorMessage, err.Data)
return
}
xResult.SuccessHasData(c, "操作成功", result)
}
```
在 Logic 层 [#在-logic-层]
```go
import xError "github.com/bamboo-services/bamboo-base-go/common/error"
func (l *SomeLogic) DoSomething(ctx context.Context) (*Result, *xError.Error) {
if someCondition {
return nil, xError.NewError(ctx, xError.ParameterEmpty, "参数为空", false, nil)
}
if someError {
return nil, xError.NewError(ctx, xError.OperationFailed, "操作失败", false, someErr)
}
return &Result{}, nil
}
```
OAuth2 特定错误 [#oauth2-特定错误]
State 验证失败 [#state-验证失败]
```json
{
"code": 401,
"message": "验证器不存在",
"data": null
}
```
**原因:**
* State 不存在或已过期
* State 已被使用(重放攻击)
Code 换取 Token 失败 [#code-换取-token-失败]
```json
{
"code": 401,
"message": "未登录",
"data": null
}
```
**原因:**
* 授权码无效或已过期
* PKCE Verifier 不匹配
* 客户端凭证错误
gRPC 错误 [#grpc-错误]
Connect-RPC 使用标准的 gRPC 错误码:
| 错误码 | 说明 |
| -------------------- | ----- |
| `canceled` | 操作被取消 |
| `unknown` | 未知错误 |
| `invalid_argument` | 参数无效 |
| `deadline_exceeded` | 超时 |
| `not_found` | 资源不存在 |
| `already_exists` | 资源已存在 |
| `permission_denied` | 权限不足 |
| `unauthenticated` | 未认证 |
| `resource_exhausted` | 资源耗尽 |
| `unavailable` | 服务不可用 |
处理 gRPC 错误 [#处理-grpc-错误]
```go
import "connectrpc.com/connect"
resp, err := client.Auth.PasswordLogin(ctx, req)
if err != nil {
if connectErr, ok := err.(*connect.Error); ok {
switch connectErr.Code() {
case connect.CodeUnauthenticated:
// 认证失败
case connect.CodeInvalidArgument:
// 参数无效
case connect.CodeUnavailable:
// 服务不可用
}
}
return
}
```
错误处理最佳实践 [#错误处理最佳实践]
1. **始终检查错误** - 不要忽略任何错误返回值
2. **使用适当的日志级别** - 错误用 Error,警告用 Warn
3. **提供有意义的错误信息** - 便于调试和用户理解
4. **不要暴露敏感信息** - 如 Token、密码等
5. **区分客户端和服务端错误** - 4xx vs 5xx
# API 参考 (/docs/beacon-sso/go-sdk/api)
API 参考 [#api-参考]
本章节提供 SDK 的完整 API 参考。
子文档 [#子文档]
所有数据模型的字段说明
常见错误码及处理方式
核心包 [#核心包]
| 包路径 | 说明 |
| --------------------------------------------------- | ---------- |
| `github.com/phalanx-labs/beacon-sso-sdk/startup` | 依赖注入节点 |
| `github.com/phalanx-labs/beacon-sso-sdk/route` | Gin 路由注册 |
| `github.com/phalanx-labs/beacon-sso-sdk/handler` | HTTP 请求处理器 |
| `github.com/phalanx-labs/beacon-sso-sdk/logic` | 业务逻辑层 |
| `github.com/phalanx-labs/beacon-sso-sdk/client` | gRPC 客户端 |
| `github.com/phalanx-labs/beacon-sso-sdk/middleware` | Gin 中间件 |
| `github.com/phalanx-labs/beacon-sso-sdk/models` | 数据模型 |
| `github.com/phalanx-labs/beacon-sso-sdk/repository` | 数据仓储 |
| `github.com/phalanx-labs/beacon-sso-sdk/constant` | 常量定义 |
| `github.com/phalanx-labs/beacon-sso-sdk/utility` | 工具函数 |
# 数据模型 (/docs/beacon-sso/go-sdk/api/models)
数据模型 [#数据模型]
本页面列出 SDK 中所有核心数据模型。
OAuth2 模型 [#oauth2-模型]
CacheOAuth [#cacheoauth]
OAuth2 State 和 PKCE Verifier 的缓存模型。
```go
type CacheOAuth struct {
State string // 随机状态码(32 位大写字母)
Verifier string // PKCE Code Verifier
}
```
| 字段 | 类型 | 说明 |
| ---------- | ------ | ---------------------- |
| `State` | string | 用于验证请求完整性的随机状态码 |
| `Verifier` | string | PKCE 流程的 Code Verifier |
**Redis Key:** `oauth:state:{state}`
**TTL:** 15 分钟
***
CacheOAuthToken [#cacheoauthtoken]
OAuth2 Token 的缓存模型。
```go
type CacheOAuthToken struct {
AccessToken string // 访问令牌
TokenType string // 令牌类型(Bearer)
RefreshToken string // 刷新令牌
Expiry string // 过期时间(RFC3339 格式)
}
```
| 字段 | 类型 | 说明 |
| -------------- | ------ | ----------------- |
| `AccessToken` | string | 访问令牌 |
| `TokenType` | string | 令牌类型,通常为 "Bearer" |
| `RefreshToken` | string | 用于刷新 Access Token |
| `Expiry` | string | 过期时间,RFC3339 格式 |
**Redis Key:** `oauth:token:{accessToken}`
**TTL:** 30 天
***
OAuthUserinfo [#oauthuserinfo]
OAuth2 Userinfo Endpoint 的响应模型。
```go
type OAuthUserinfo struct {
Sub string // 用户唯一标识
Nickname string // 昵称
PreferredUsername string // 首选用户名
Email string // 邮箱
Phone string // 手机号
Raw map[string]any // 原始响应数据
}
```
| 字段 | 类型 | 说明 |
| ------------------- | --------------- | ----------------- |
| `Sub` | string | 用户唯一标识(来自 OIDC) |
| `Nickname` | string | 用户昵称 |
| `PreferredUsername` | string | 用户首选用户名 |
| `Email` | string | 用户邮箱 |
| `Phone` | string | 用户手机号 |
| `Raw` | map\[string]any | 原始 JSON 响应,包含扩展字段 |
**Redis Key:** `oauth:biz:userinfo:{accessToken}`
**TTL:** 30 秒(受 `SSO_BUSINESS_CACHE` 控制)
***
OAuthIntrospection [#oauthintrospection]
OAuth2 Introspection Endpoint 的响应模型。
```go
type OAuthIntrospection struct {
Active bool // 令牌是否有效
TokenType string // 令牌类型
Exp int64 // 过期时间戳(Unix)
Expiry string // 过期时间(RFC3339)
ExpiresIn int64 // 剩余有效时间(秒)
IsExpired bool // 是否已过期
Raw map[string]any // 原始响应数据
}
```
| 字段 | 类型 | 说明 |
| ----------- | --------------- | ---------------- |
| `Active` | bool | 令牌是否有效 |
| `TokenType` | string | 令牌类型 |
| `Exp` | int64 | 过期时间戳(Unix 秒) |
| `Expiry` | string | 过期时间(RFC3339 格式) |
| `ExpiresIn` | int64 | 剩余有效时间(秒) |
| `IsExpired` | bool | 是否已过期 |
| `Raw` | map\[string]any | 原始 JSON 响应 |
**Redis Key:** `oauth:biz:introspection:{tokenType}:{token}`
**TTL:** 动态(取 min(expiresIn, 30s))
***
业务缓存模型 [#业务缓存模型]
CacheBusinessUserinfo [#cachebusinessuserinfo]
业务层 Userinfo 的 Redis Hash 存储模型。
```go
type CacheBusinessUserinfo struct {
Sub string // 用户唯一标识
Raw string // 原始 JSON 字符串
}
```
***
CacheBusinessIntrospection [#cachebusinessintrospection]
业务层 Introspection 的 Redis Hash 存储模型。
```go
type CacheBusinessIntrospection struct {
Active bool // 令牌是否有效
TokenType string // 令牌类型
Exp int64 // 过期时间戳
ExpiresIn int64 // 剩余有效时间
IsExpired bool // 是否已过期
Raw string // 原始 JSON 字符串
}
```
***
gRPC 消息类型 [#grpc-消息类型]
SendRegisterEmailCodeRequest [#sendregisteremailcoderequest]
```go
type SendRegisterEmailCodeRequest struct {
Email string // 目标邮箱地址
}
```
RegisterByEmailRequest [#registerbyemailrequest]
```go
type RegisterByEmailRequest struct {
Email string // 邮箱地址
Code string // 验证码
Username string // 用户名
Password string // 密码
Nickname string // 昵称(可选)
}
```
RegisterByEmailResponse [#registerbyemailresponse]
```go
type RegisterByEmailResponse struct {
UserId string // 用户 ID
AccessToken string // 访问令牌
RefreshToken string // 刷新令牌
ExpiresIn int64 // 过期时间(秒)
}
```
PasswordLoginRequest [#passwordloginrequest]
```go
type PasswordLoginRequest struct {
Username string // 用户名/邮箱/手机号
Password string // 密码
Scope string // 权限范围
}
```
PasswordLoginResponse [#passwordloginresponse]
```go
type PasswordLoginResponse struct {
AccessToken string // 访问令牌
TokenType string // 令牌类型
RefreshToken string // 刷新令牌
ExpiresIn int64 // 过期时间(秒)
IdToken string // ID Token(可选)
}
```
ChangePasswordRequest [#changepasswordrequest]
```go
type ChangePasswordRequest struct {
UserId string // 用户 ID
OldPassword string // 旧密码(普通模式必填)
NewPassword string // 新密码
NeedResetPassword bool // 是否强制重置模式
}
```
RevokeTokenRequest [#revoketokenrequest]
```go
type RevokeTokenRequest struct {
TokenTypeHint string // 令牌类型提示(可选)
}
```
GetUserByIDRequest [#getuserbyidrequest]
```go
type GetUserByIDRequest struct {
UserId string // 用户 ID
}
```
# Auth 服务 (/docs/beacon-sso/go-sdk/grpc/auth-service)
Auth 服务 [#auth-服务]
Auth 服务提供用户认证相关功能,包括注册、登录、修改密码和注销令牌。
Auth 服务需要在 metadata 中提供有效的 App 凭证(`app-access-id` 和 `app-secret-key`)。
接口概览 [#接口概览]
| 方法 | 说明 | 返回 Token |
| ----------------- | ---- | -------- |
| `RegisterByEmail` | 邮箱注册 | ✓ |
| `PasswordLogin` | 密码登录 | ✓ |
| `ChangePassword` | 修改密码 | ✗ |
| `RevokeToken` | 注销令牌 | ✗ |
RegisterByEmail [#registerbyemail]
通过邮箱验证码完成用户注册,注册成功后自动生成登录 Token。
请求参数 [#请求参数]
```go
type RegisterByEmailRequest struct {
Email string // 邮箱地址
Code string // 验证码
Username string // 用户名
Password string // 密码
Nickname string // 昵称(可选)
}
```
响应 [#响应]
```go
type RegisterByEmailResponse struct {
UserId string // 用户 ID
AccessToken string // 访问令牌
RefreshToken string // 刷新令牌
ExpiresIn int64 // 过期时间(秒)
}
```
使用示例 [#使用示例]
```go
// 1. 先发送验证码
_, err := client.Public.SendRegisterEmailCode(ctx, &pb.SendRegisterEmailCodeRequest{
Email: "user@example.com",
})
// 2. 用户输入验证码后注册
resp, err := client.Auth.RegisterByEmail(ctx, &pb.RegisterByEmailRequest{
Email: "user@example.com",
Code: "123456",
Username: "newuser",
Password: "SecurePass123!",
Nickname: "New User",
})
fmt.Printf("注册成功!用户 ID: %s\n", resp.UserId)
fmt.Printf("Access Token: %s\n", resp.AccessToken)
```
PasswordLogin [#passwordlogin]
实现 OAuth 2.0 Resource Owner Password Credentials Grant,允许受信任的第一方客户端直接使用用户名和密码换取 Token。
安全限制 [#安全限制]
* **仅限第一方应用**(`App.FirstParty = enabled`)
* 支持用户名/邮箱/手机号三种登录方式(自动识别)
请求参数 [#请求参数-1]
```go
type PasswordLoginRequest struct {
Username string // 用户名/邮箱/手机号
Password string // 密码
Scope string // 权限范围(如 "openid profile email")
}
```
响应 [#响应-1]
```go
type PasswordLoginResponse struct {
AccessToken string // 访问令牌
TokenType string // 令牌类型(通常为 "Bearer")
RefreshToken string // 刷新令牌
ExpiresIn int64 // 过期时间(秒)
IdToken string // ID Token(可选)
}
```
使用示例 [#使用示例-1]
```go
resp, err := client.Auth.PasswordLogin(ctx, &pb.PasswordLoginRequest{
Username: "user@example.com",
Password: "SecurePass123!",
Scope: "openid profile email",
})
if err != nil {
panic(err)
}
fmt.Printf("登录成功!\n")
fmt.Printf("Access Token: %s\n", resp.AccessToken)
fmt.Printf("过期时间: %d 秒\n", resp.ExpiresIn)
```
密码登录会自动缓存 Token 到 Redis,可通过 `OAuthLogic.GetToken()` 获取。
ChangePassword [#changepassword]
修改用户密码,支持普通模式和强制重置模式。
模式说明 [#模式说明]
| 模式 | 条件 | 旧密码 |
| ------ | ------------------------- | --- |
| 普通模式 | `NeedResetPassword=false` | 必填 |
| 强制重置模式 | `NeedResetPassword=true` | 可省略 |
请求参数 [#请求参数-2]
```go
type ChangePasswordRequest struct {
UserId string // 用户 ID
OldPassword string // 旧密码(普通模式必填)
NewPassword string // 新密码
NeedResetPassword bool // 是否强制重置模式
}
```
响应 [#响应-2]
```go
type ChangePasswordResponse struct {
// 基础响应信息
}
```
使用示例 [#使用示例-2]
```go
// 普通模式修改密码
_, err := client.Auth.ChangePassword(ctx, &pb.ChangePasswordRequest{
UserId: "user-123",
OldPassword: "OldPass123!",
NewPassword: "NewSecurePass456!",
})
// 强制重置模式(管理员场景)
_, err := client.Auth.ChangePassword(ctx, &pb.ChangePasswordRequest{
UserId: "user-123",
NewPassword: "NewSecurePass456!",
NeedResetPassword: true,
})
```
RevokeToken [#revoketoken]
注销用户 Token,实现用户登出功能。符合 RFC 7009 OAuth 2.0 Token Revocation 规范。
使用场景 [#使用场景]
* 用户主动登出
* Token 泄露后的紧急注销
请求参数 [#请求参数-3]
```go
type RevokeTokenRequest struct {
TokenTypeHint string // 令牌类型提示(access_token/refresh_token,可选)
}
// 方法签名
func (s *AuthService) RevokeToken(
ctx context.Context,
accessToken string, // 用户访问令牌
req *pb.RevokeTokenRequest,
) (*pb.RevokeTokenResponse, error)
```
使用示例 [#使用示例-3]
```go
// 注销 Access Token
_, err := client.Auth.RevokeToken(ctx, accessToken, &pb.RevokeTokenRequest{
TokenTypeHint: "access_token",
})
// 注销 Refresh Token
_, err := client.Auth.RevokeToken(ctx, refreshToken, &pb.RevokeTokenRequest{
TokenTypeHint: "refresh_token",
})
```
SDK 的 HTTP 路由层调用 `RevokeToken` 后会自动清理本地 Redis 缓存。
HTTP 路由 [#http-路由]
SDK 提供以下 Auth 相关 HTTP 路由:
| 方法 | 路径 | 说明 |
| ---- | ------------------------------ | --------- |
| POST | `/api/account/register/email` | 邮箱注册 |
| POST | `/api/account/login/password` | 密码登录 |
| POST | `/api/account/password/change` | 修改密码(需认证) |
| POST | `/api/account/token/revoke` | 注销令牌(需认证) |
# gRPC 服务 (/docs/beacon-sso/go-sdk/grpc)
gRPC 服务 [#grpc-服务]
gRPC 服务基于 Connect-RPC 协议实现,提供认证、用户和商户三大服务。
协议说明 [#协议说明]
SDK 使用 [Connect-RPC](https://connectrpc.com/) 协议,这是一种基于 HTTP/2 的 gRPC 兼容协议,具有以下特点:
* 完全兼容 gRPC
* 支持 HTTP/2 明文传输(h2c)
* 自动生成类型安全的客户端代码
SsoClient 初始化 [#ssoclient-初始化]
Option 模式 [#option-模式]
SDK 使用 Option 模式初始化客户端:
```go
import bSdkClient "github.com/phalanx-labs/beacon-sso-sdk/client"
client := bSdkClient.NewClient(
bSdkClient.WithConnect("sso.example.com", "5566"),
bSdkClient.WithAppAccess("your-app-id", "your-app-secret"),
)
```
可用 Option [#可用-option]
| Option | 说明 |
| --------------------------------- | ---------------------- |
| `WithConnect(host, port)` | 设置 gRPC 主机地址和端口 |
| `WithAppAccess(id, secret)` | 设置 App 认证凭证 |
| `WithProtoPublicClient(client)` | 直接注入 Public 客户端(测试用) |
| `WithProtoAuthClient(client)` | 直接注入 Auth 客户端(测试用) |
| `WithProtoMerchantClient(client)` | 直接注入 Merchant 客户端(测试用) |
| `WithProtoUserClient(client)` | 直接注入 User 客户端(测试用) |
通过依赖注入获取 [#通过依赖注入获取]
如果你的项目已集成 SDK 的 Startup 节点,可以从上下文中获取:
```go
import bSdkUtil "github.com/phalanx-labs/beacon-sso-sdk/utility"
client := bSdkUtil.GetSsoClient(ctx)
```
服务概览 [#服务概览]
| 服务 | 说明 | 认证要求 |
| ------------------------------ | ---- | ------------------- |
| [Public](./public-service) | 公共服务 | 无 |
| [Auth](./auth-service) | 认证服务 | App 凭证 |
| [User](./user-service) | 用户服务 | App 凭证 + User Token |
| [Merchant](./merchant-service) | 商户服务 | App 凭证 |
认证机制 [#认证机制]
App 凭证 [#app-凭证]
Auth、User、Merchant 服务需要在 gRPC metadata 中提供 App 凭证:
```go
// metadata 中会自动注入
// app-access-id: your-app-id
// app-secret-key: your-app-secret
```
User Token [#user-token]
User 服务还需要在 metadata 中提供用户 Token:
```go
// metadata 中会自动注入
// authorization: Bearer {accessToken}
```
服务封装层会自动处理 metadata 注入,你只需在调用时传入 accessToken 参数。
使用示例 [#使用示例]
```go
import (
"context"
bSdkClient "github.com/phalanx-labs/beacon-sso-sdk/client"
pb "github.com/phalanx-labs/beacon-sso-sdk/client/api/beacon/sso/v1"
)
func main() {
ctx := context.Background()
// 创建客户端
client := bSdkClient.NewClient(
bSdkClient.WithConnect("sso.example.com", "5566"),
bSdkClient.WithAppAccess("app-id", "app-secret"),
)
// 使用 Public 服务
_, err := client.Public.SendRegisterEmailCode(ctx, &pb.SendRegisterEmailCodeRequest{
Email: "user@example.com",
})
// 使用 Auth 服务
loginResp, err := client.Auth.PasswordLogin(ctx, &pb.PasswordLoginRequest{
Username: "user@example.com",
Password: "password123",
Scope: "openid profile email",
})
// 使用 User 服务(需要 accessToken)
userResp, err := client.User.GetCurrentUser(ctx, loginResp.AccessToken)
// 使用 Merchant 服务
tagsResp, err := client.Merchant.GetMerchantTags(ctx, &service.GetMerchantTagsRequest{})
}
```
子文档 [#子文档]
发送注册验证码等公共功能
注册、登录、修改密码、注销令牌
获取用户信息
商户标签、公告管理
# Merchant 服务 (/docs/beacon-sso/go-sdk/grpc/merchant-service)
Merchant 服务 [#merchant-服务]
Merchant 服务提供商户标签和公告管理功能。
Merchant 服务需要在 metadata 中提供 App 凭证(`app-access-id` 和 `app-secret-key`)。
接口概览 [#接口概览]
| 方法 | 说明 |
| ------------------------ | ----------- |
| `GetMerchantTags` | 获取商户标签列表 |
| `GetUserTags` | 获取用户标签列表 |
| `CheckUserHasTag` | 检查用户是否有指定标签 |
| `GetRecentAnnouncements` | 获取最近公告列表 |
| `GetAnnouncement` | 获取单个公告详情 |
标签系统 [#标签系统]
GetMerchantTags [#getmerchanttags]
获取当前应用所属商户的所有标签列表。
```go
import service "github.com/phalanx-labs/beacon-sso-sdk/client/service"
tags, err := client.Merchant.GetMerchantTags(ctx, &service.GetMerchantTagsRequest{})
if err != nil {
panic(err)
}
for _, tag := range tags.Tags {
fmt.Printf("标签: %s (%s)\n", tag.Name, tag.Code)
}
```
GetUserTags [#getusertags]
获取指定用户在当前商户的所有标签。
```go
tags, err := client.Merchant.GetUserTags(ctx, &service.GetUserTagsRequest{
UserId: "user-123",
})
for _, tag := range tags.Tags {
fmt.Printf("用户标签: %s\n", tag.Name)
}
```
CheckUserHasTag [#checkuserhastag]
通过标签代码快速检查用户是否拥有该标签。
```go
result, err := client.Merchant.CheckUserHasTag(ctx, &service.CheckUserHasTagRequest{
UserId: "user-123",
TagCode: "vip",
})
if result.HasTag {
fmt.Println("用户是 VIP")
} else {
fmt.Println("用户不是 VIP")
}
```
公告系统 [#公告系统]
GetRecentAnnouncements [#getrecentannouncements]
获取当前应用所属商户的最近公告(最多 10 条)。
**响应包含哈希值:** 返回结果包含 MD5 和 SHA256 哈希值,客户端可用于判断公告内容是否变化,决定是否需要重新展示。
```go
announcements, err := client.Merchant.GetRecentAnnouncements(ctx, &service.GetRecentAnnouncementsRequest{})
if err != nil {
panic(err)
}
for _, ann := range announcements.Announcements {
fmt.Printf("公告: %s\n", ann.Title)
fmt.Printf(" MD5: %s\n", ann.Md5Hash)
fmt.Printf(" SHA256: %s\n", ann.Sha256Hash)
}
```
GetAnnouncement [#getannouncement]
根据公告 ID 获取详细信息。
```go
announcement, err := client.Merchant.GetAnnouncement(ctx, &service.GetAnnouncementRequest{
AnnouncementId: "ann-123",
})
if err != nil {
panic(err)
}
fmt.Printf("标题: %s\n", announcement.Title)
fmt.Printf("内容: %s\n", announcement.Content)
```
使用场景 [#使用场景]
用户权限控制 [#用户权限控制]
```go
// 检查用户是否有管理员标签
func IsAdmin(ctx context.Context, client *bSdkClient.SsoClient, userId string) bool {
result, err := client.Merchant.CheckUserHasTag(ctx, &service.CheckUserHasTagRequest{
UserId: userId,
TagCode: "admin",
})
if err != nil {
return false
}
return result.HasTag
}
```
功能开关 [#功能开关]
```go
// 根据用户标签决定是否启用某功能
func CanAccessPremiumFeature(ctx context.Context, client *bSdkClient.SsoClient, userId string) bool {
tags, err := client.Merchant.GetUserTags(ctx, &service.GetUserTagsRequest{
UserId: userId,
})
if err != nil {
return false
}
for _, tag := range tags.Tags {
if tag.Code == "premium" || tag.Code == "vip" {
return true
}
}
return false
}
```
公告缓存 [#公告缓存]
```go
// 使用哈希值判断公告是否变化
type AnnouncementCache struct {
LastHash string
Content []Announcement
}
func GetAnnouncementsWithCache(ctx context.Context, client *bSdkClient.SsoClient, cache *AnnouncementCache) []Announcement {
resp, _ := client.Merchant.GetRecentAnnouncements(ctx, &service.GetRecentAnnouncementsRequest{})
// 计算整体哈希
currentHash := calculateCombinedHash(resp.Announcements)
if currentHash == cache.LastHash {
// 内容未变化,使用缓存
return cache.Content
}
// 内容已变化,更新缓存
cache.LastHash = currentHash
cache.Content = resp.Announcements
return cache.Content
}
```
# Public 服务 (/docs/beacon-sso/go-sdk/grpc/public-service)
Public 服务 [#public-服务]
Public 服务提供无需认证的公共功能,主要用于发送验证码。
接口概览 [#接口概览]
| 方法 | 说明 | 认证 |
| ----------------------- | --------- | -- |
| `SendRegisterEmailCode` | 发送注册邮箱验证码 | 无 |
SendRegisterEmailCode [#sendregisteremailcode]
发送注册邮箱验证码。
请求参数 [#请求参数]
```go
type SendRegisterEmailCodeRequest struct {
Email string // 目标邮箱地址
}
```
响应 [#响应]
```go
type SendRegisterEmailCodeResponse struct {
// 基础响应信息
}
```
使用示例 [#使用示例]
```go
import (
"context"
bSdkClient "github.com/phalanx-labs/beacon-sso-sdk/client"
pb "github.com/phalanx-labs/beacon-sso-sdk/client/api/beacon/sso/v1"
)
func main() {
ctx := context.Background()
// 创建客户端(Public 服务无需 App 凭证)
client := bSdkClient.NewClient(
bSdkClient.WithConnect("sso.example.com", "5566"),
)
// 发送验证码
_, err := client.Public.SendRegisterEmailCode(ctx, &pb.SendRegisterEmailCodeRequest{
Email: "user@example.com",
})
if err != nil {
panic(err)
}
println("验证码已发送")
}
```
限制说明 [#限制说明]
| 限制 | 说明 |
| ---- | -------------------------------------------- |
| 有效期 | 15 分钟(可通过 `EMAIL_VERIFY_CODE_EXPIRE` 环境变量配置) |
| 频率限制 | 同一邮箱 1 分钟内只能发送一次 |
错误码 [#错误码]
| 错误 | 说明 |
| -------------------- | ------- |
| `invalid_argument` | 邮箱格式无效 |
| `resource_exhausted` | 发送频率超限 |
| `unavailable` | 邮件服务不可用 |
HTTP 路由 [#http-路由]
SDK 同时提供 HTTP 路由封装:
```bash
POST /api/account/register/email-code
Content-Type: application/json
{
"email": "user@example.com"
}
```
# User 服务 (/docs/beacon-sso/go-sdk/grpc/user-service)
User 服务 [#user-服务]
User 服务提供用户信息查询功能。
User 服务需要在 metadata 中提供 App 凭证和用户 Token。
接口概览 [#接口概览]
| 方法 | 说明 | Token 来源 |
| ---------------- | ------------ | ------------- |
| `GetCurrentUser` | 获取当前登录用户信息 | 从 Token 中提取 |
| `GetUserByID` | 根据用户 ID 获取信息 | 需要提供 user\_id |
GetCurrentUser [#getcurrentuser]
获取当前登录用户的详细信息。
方法签名 [#方法签名]
```go
func (s *UserService) GetCurrentUser(
ctx context.Context,
accessToken string,
) (*pb.GetCurrentUserResponse, error)
```
响应 [#响应]
```go
type GetCurrentUserResponse struct {
UserId string // 用户 ID
Username string // 用户名
Nickname string // 昵称
Email string // 邮箱
Phone string // 手机号
Avatar string // 头像 URL
Status int32 // 状态
// ... 其他字段
}
```
使用示例 [#使用示例]
```go
import (
"context"
bSdkClient "github.com/phalanx-labs/beacon-sso-sdk/client"
)
func main() {
ctx := context.Background()
client := bSdkClient.NewClient(
bSdkClient.WithConnect("sso.example.com", "5566"),
bSdkClient.WithAppAccess("app-id", "app-secret"),
)
// 假设 accessToken 来自登录响应或请求头
accessToken := "eyJhbGciOiJSUzI1NiIs..."
// 获取当前用户信息
user, err := client.User.GetCurrentUser(ctx, accessToken)
if err != nil {
panic(err)
}
fmt.Printf("用户 ID: %s\n", user.UserId)
fmt.Printf("用户名: %s\n", user.Username)
fmt.Printf("邮箱: %s\n", user.Email)
}
```
GetUserByID [#getuserbyid]
根据用户 ID 获取指定用户的详细信息。主要用于接入 App 需要获取其他用户信息的场景。
与 GetCurrentUser 的区别 [#与-getcurrentuser-的区别]
| 方法 | 信息来源 | 用途 |
| ---------------- | -------------- | ---------- |
| `GetCurrentUser` | 从 Token 中获取 | 获取当前登录用户信息 |
| `GetUserByID` | 通过 user\_id 参数 | 获取任意用户信息 |
方法签名 [#方法签名-1]
```go
func (s *UserService) GetUserByID(
ctx context.Context,
accessToken string,
req *pb.GetUserByIDRequest,
) (*pb.GetUserByIDResponse, error)
```
请求参数 [#请求参数]
```go
type GetUserByIDRequest struct {
UserId string // 目标用户 ID
}
```
响应 [#响应-1]
```go
type GetUserByIDResponse struct {
UserId string // 用户 ID
Username string // 用户名
Nickname string // 昵称
Email string // 邮箱
Phone string // 手机号
Avatar string // 头像 URL
Status int32 // 状态
// ... 其他字段
}
```
使用示例 [#使用示例-1]
```go
// 获取指定用户信息
user, err := client.User.GetUserByID(ctx, accessToken, &pb.GetUserByIDRequest{
UserId: "target-user-123",
})
if err != nil {
panic(err)
}
fmt.Printf("用户名: %s\n", user.Username)
```
HTTP 路由 [#http-路由]
SDK 提供以下 User 相关 HTTP 路由:
| 方法 | 路径 | 认证 | 说明 |
| --- | -------------------- | --------- | ------------ |
| GET | `/api/user/userinfo` | CheckAuth | 获取当前用户信息 |
| GET | `/api/user/by-id` | CheckAuth | 根据 ID 获取用户信息 |
请求示例 [#请求示例]
```bash
# 获取当前用户信息
GET /api/user/userinfo HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
# 根据 ID 获取用户信息
GET /api/user/by-id?user_id=target-user-123 HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
# 认证检查中间件 (/docs/beacon-sso/go-sdk/middleware/auth-check)
CheckAuth 中间件 [#checkauth-中间件]
`CheckAuth` 是一个 Gin 中间件,用于验证请求中的 Access Token 是否有效。
功能说明 [#功能说明]
该中间件执行以下验证流程:
1. 从请求头 `Authorization` 提取 Access Token
2. 调用 `OAuthLogic.VerifyExpiry()` 验证 Token 是否过期
3. 验证通过后将 Token 存入 Gin Context
4. 验证失败则中断请求并返回错误
使用方法 [#使用方法]
函数签名 [#函数签名]
```go
func CheckAuth(ctx context.Context) gin.HandlerFunc
```
全局使用 [#全局使用]
```go
func main() {
// ... 初始化代码 ...
reg := xReg.Register(context.Background(), nodes)
// 全局使用中间件
reg.Serve.Use(bSdkMiddleware.CheckAuth(reg.Init.Ctx))
// 所有路由都需要认证
reg.Serve.GET("/api/protected", protectedHandler)
}
```
路由组使用 [#路由组使用]
```go
func main() {
// ... 初始化代码 ...
reg := xReg.Register(context.Background(), nodes)
// 公开路由
reg.Serve.GET("/api/public", publicHandler)
// 需要认证的路由组
protected := reg.Serve.Group("/api")
protected.Use(bSdkMiddleware.CheckAuth(reg.Init.Ctx))
protected.GET("/user", userHandler)
protected.GET("/profile", profileHandler)
}
```
单个路由使用 [#单个路由使用]
```go
reg.Serve.GET("/api/sensitive",
bSdkMiddleware.CheckAuth(reg.Init.Ctx),
sensitiveHandler,
)
```
工作流程 [#工作流程]
从 Context 获取 Token [#从-context-获取-token]
中间件验证通过后,Token 会被存入 Gin Context:
```go
func protectedHandler(c *gin.Context) {
// 获取已验证的 Access Token
token, exists := c.Get("authorization")
if !exists {
c.JSON(500, gin.H{"error": "token not found"})
return
}
accessToken := token.(string)
// 使用 token 调用其他服务...
}
```
错误响应 [#错误响应]
| 错误码 | 说明 | HTTP 状态码 |
| ---------------- | -------------------- | -------- |
| `ParameterEmpty` | Authorization 头缺失或为空 | 400 |
| `NotExist` | Token 在缓存中不存在 | 401 |
| `TokenExpired` | Token 已过期 | 401 |
错误响应示例 [#错误响应示例]
```json
{
"code": 401,
"message": "访问令牌已过期",
"data": null
}
```
完整示例 [#完整示例]
```go
package main
import (
"context"
xConsts "github.com/bamboo-services/bamboo-base-go/defined/context"
xReg "github.com/bamboo-services/bamboo-base-go/major/register"
xRegNode "github.com/bamboo-services/bamboo-base-go/major/register/node"
xResult "github.com/bamboo-services/bamboo-base-go/major/result"
"github.com/gin-gonic/gin"
bSdkMiddleware "github.com/phalanx-labs/beacon-sso-sdk/middleware"
bSdkStartup "github.com/phalanx-labs/beacon-sso-sdk/startup"
)
func main() {
nodes := []xRegNode.RegNodeList{
{Key: xConsts.DatabaseKey, Node: initDatabase},
{Key: xConsts.RedisClientKey, Node: initRedis},
}
nodes = append(nodes, bSdkStartup.NewStartupConfig()...)
reg := xReg.Register(context.Background(), nodes)
// 公开路由
reg.Serve.GET("/api/health", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "ok"})
})
// 需要认证的路由
protected := reg.Serve.Group("/api")
protected.Use(bSdkMiddleware.CheckAuth(reg.Init.Ctx))
protected.GET("/me", func(c *gin.Context) {
token, _ := c.Get("authorization")
xResult.SuccessHasData(c, "获取成功", gin.H{
"token": token,
})
})
_ = reg.Serve.Run(":8080")
}
```
# 中间件 (/docs/beacon-sso/go-sdk/middleware)
中间件 [#中间件]
SDK 提供 Gin 中间件,用于在请求处理前进行身份验证。
可用中间件 [#可用中间件]
| 中间件 | 说明 |
| ------------------------- | ----------- |
| [CheckAuth](./auth-check) | Token 验证中间件 |
使用示例 [#使用示例]
```go
import (
bSdkMiddleware "github.com/phalanx-labs/beacon-sso-sdk/middleware"
)
// 全局使用
reg.Serve.Use(bSdkMiddleware.CheckAuth(reg.Init.Ctx))
// 路由组使用
api := reg.Serve.Group("/api")
api.Use(bSdkMiddleware.CheckAuth(reg.Init.Ctx))
// 单个路由使用
reg.Serve.GET("/protected",
bSdkMiddleware.CheckAuth(reg.Init.Ctx),
handler,
)
```
# 授权码流程 (/docs/beacon-sso/go-sdk/oauth2/flow)
授权码流程 [#授权码流程]
本文档详细介绍 OAuth2 授权码流程的实现细节,包括 State 防护和 PKCE 安全机制。
流程概览 [#流程概览]
OAuthLogic 核心方法 [#oauthlogic-核心方法]
Create - 创建 State 和 PKCE [#create---创建-state-和-pkce]
```go
func (l *OAuthLogic) Create(ctx context.Context) (*bSdkModels.CacheOAuth, *xError.Error)
```
生成随机的 State 字符串和 PKCE Code Verifier,并存储到 Redis。
**返回值:**
* `CacheOAuth.State` - 随机状态码(32 位大写字母)
* `CacheOAuth.Verifier` - PKCE Code Verifier
**缓存策略:**
* Key: `oauth:state:{state}`
* TTL: 15 分钟
BuildURL - 构建授权 URL [#buildurl---构建授权-url]
```go
func (l *OAuthLogic) BuildURL(ctx context.Context, oAuth *bSdkModels.CacheOAuth) (string, *xError.Error)
```
根据 State 和 Verifier 构建完整的 OAuth2 授权跳转 URL。
**PKCE 模式:** 使用 S256(SHA-256)Challenge 方法
**生成的 URL 示例:**
```
https://sso.example.com/oauth/authorize
?client_id=xxx
&redirect_uri=http://localhost:8080/api/oauth/callback
&response_type=code
&state=ABCD1234...
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
```
Verify - 验证 State [#verify---验证-state]
```go
func (l *OAuthLogic) Verify(ctx context.Context, state string) (*bSdkModels.CacheOAuth, *xError.Error)
```
从 Redis 中获取 State 对应的 PKCE Verifier,验证成功后删除缓存(防止重放攻击)。
**错误情况:**
* State 为空
* Redis 中不存在该 State
* Verifier 为空
Exchange - 用 Code 换 Token [#exchange---用-code-换-token]
```go
func (l *OAuthLogic) Exchange(ctx context.Context, code string, verifier string) (*oauth2.Token, *xError.Error)
```
使用授权码和 PKCE Verifier 向 SSO Server 请求 Access Token。
**自动缓存:** 成功获取 Token 后自动缓存到 Redis
安全机制 [#安全机制]
State 防护 [#state-防护]
State 参数用于防止 CSRF 攻击:
1. 用户发起登录时生成随机 State
2. 将 State 存储到 Redis
3. 回调时验证 State 是否匹配
4. 验证成功后立即删除(防重放)
PKCE 增强 [#pkce-增强]
PKCE (Proof Key for Code Exchange) 防止授权码劫持:
1. 生成随机 Code Verifier
2. 计算 Code Challenge = BASE64URL(SHA256(Verifier))
3. 授权请求携带 Challenge
4. Token 请求携带 Verifier
5. 服务端验证 Verifier 与 Challenge 匹配
PKCE 是 OAuth2 推荐的安全增强措施,强烈建议始终启用。
直接使用 OAuthLogic [#直接使用-oauthlogic]
如果你需要自定义路由或处理逻辑,可以直接使用 OAuthLogic:
```go
import (
"context"
bSdkLogic "github.com/phalanx-labs/beacon-sso-sdk/logic"
)
func handleLogin(c *gin.Context) {
ctx := c.Request.Context()
oauthLogic := bSdkLogic.NewOAuth(ctx)
// 1. 创建 State 和 PKCE
oauth, err := oauthLogic.Create(ctx)
if err != nil {
// 处理错误
return
}
// 2. 构建跳转 URL
authURL, err := oauthLogic.BuildURL(ctx, oauth)
if err != nil {
// 处理错误
return
}
// 3. 重定向
c.Redirect(302, authURL)
}
func handleCallback(c *gin.Context) {
ctx := c.Request.Context()
code := c.Query("code")
state := c.Query("state")
oauthLogic := bSdkLogic.NewOAuth(ctx)
// 1. 验证 State
oauth, err := oauthLogic.Verify(ctx, state)
if err != nil {
// State 无效
return
}
// 2. 用 Code 换 Token
token, err := oauthLogic.Exchange(ctx, code, oauth.Verifier)
if err != nil {
// 换取失败
return
}
// 使用 token.AccessToken...
}
```
# OAuth2 子系统 (/docs/beacon-sso/go-sdk/oauth2)
OAuth2 子系统 [#oauth2-子系统]
OAuth2 子系统基于 `golang.org/x/oauth2` 官方库扩展,提供完整的授权码流程支持,包含 State 防护和 PKCE 安全增强。
核心特性 [#核心特性]
* **授权码流程** - 标准 OAuth2 Authorization Code Flow
* **State 防护** - 防止 CSRF 攻击
* **PKCE 增强** - S256 Challenge 模式,防止授权码劫持
* **Token 缓存** - 基于 Redis 的 Token 自动缓存
* **自动刷新** - 使用 Refresh Token 自动更新 Access Token
架构图 [#架构图]
核心组件 [#核心组件]
| 组件 | 说明 |
| ---------------- | --------------- |
| `OAuthLogic` | OAuth 业务逻辑层 |
| `OAuthRepo` | State/PKCE 数据仓储 |
| `OAuthTokenRepo` | Token 数据仓储 |
子文档 [#子文档]
了解完整的 OAuth2 授权码流程,包括 State 验证和 PKCE 机制
了解 Token 的缓存、刷新和注销机制
查看 SDK 提供的默认 OAuth2 路由
# 默认路由 (/docs/beacon-sso/go-sdk/oauth2/routes)
默认路由 [#默认路由]
SDK 提供开箱即用的 OAuth2 路由,可通过 `OAuthRouter` 快速挂载。
路由列表 [#路由列表]
| 方法 | 路径 | 认证 | 说明 |
| ---- | ----------------- | -- | --------------------------- |
| GET | `/oauth/login` | 无 | 302 重定向到 SSO 授权页面 |
| GET | `/oauth/callback` | 无 | OAuth2 回调,用 code 换 token |
| POST | `/oauth/logout` | 无 | 注销 token(通过 Header 传 token) |
挂载路由 [#挂载路由]
```go
import bSdkRoute "github.com/phalanx-labs/beacon-sso-sdk/route"
// 挂载到 /api 前缀
sdkRoute := bSdkRoute.NewRoute(ctx)
sdkRoute.OAuthRouter(reg.Serve.Group("/api"))
// 或挂载到根路径
sdkRoute.OAuthRouter(reg.Serve.Group(""))
```
路由详情 [#路由详情]
GET /oauth/login [#get-oauthlogin]
发起 OAuth2 登录流程,重定向到 SSO 授权页面。
**请求示例:**
```bash
GET /api/oauth/login HTTP/1.1
```
**响应:**
```
HTTP/1.1 302 Found
Location: https://sso.example.com/oauth/authorize?client_id=xxx&redirect_uri=xxx&response_type=code&state=xxx&code_challenge=xxx&code_challenge_method=S256
```
GET /oauth/callback [#get-oauthcallback]
OAuth2 回调端点,处理 SSO Server 的授权响应。
**请求参数:**
| 参数 | 类型 | 说明 |
| ------- | ------ | --------- |
| `code` | string | 授权码 |
| `state` | string | 状态码(用于验证) |
**请求示例:**
```bash
GET /api/oauth/callback?code=abc123&state=XYZ789 HTTP/1.1
```
**成功响应:**
```json
{
"code": 200,
"message": "登录成功",
"data": {
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...",
"expires_in": 3600
}
}
```
**错误响应:**
| 错误码 | 说明 |
| --- | -------------------------- |
| 401 | 未登录(State 验证失败或 Code 换取失败) |
POST /oauth/logout [#post-oauthlogout]
注销当前用户的 Token。
**请求头:**
| Header | 说明 |
| --------------- | ---------------------- |
| `Authorization` | Bearer `{accessToken}` |
**请求示例:**
```bash
POST /api/oauth/logout HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
**成功响应:**
```json
{
"code": 200,
"message": "注销成功"
}
```
自定义路由前缀 [#自定义路由前缀]
你可以自由选择路由前缀:
```go
// 方式 1:挂载到 /api
sdkRoute.OAuthRouter(reg.Serve.Group("/api"))
// 路由: /api/oauth/login, /api/oauth/callback, /api/oauth/logout
// 方式 2:挂载到 /auth
sdkRoute.OAuthRouter(reg.Serve.Group("/auth"))
// 路由: /auth/oauth/login, /auth/oauth/callback, /auth/oauth/logout
// 方式 3:挂载到根路径
sdkRoute.OAuthRouter(reg.Serve.Group(""))
// 路由: /oauth/login, /oauth/callback, /oauth/logout
```
完整路由挂载示例 [#完整路由挂载示例]
```go
package main
import (
"context"
xConsts "github.com/bamboo-services/bamboo-base-go/defined/context"
xReg "github.com/bamboo-services/bamboo-base-go/major/register"
xRegNode "github.com/bamboo-services/bamboo-base-go/major/register/node"
"github.com/gin-gonic/gin"
bSdkRoute "github.com/phalanx-labs/beacon-sso-sdk/route"
bSdkStartup "github.com/phalanx-labs/beacon-sso-sdk/startup"
)
func main() {
// 初始化
nodes := []xRegNode.RegNodeList{
{Key: xConsts.DatabaseKey, Node: initDatabase},
{Key: xConsts.RedisClientKey, Node: initRedis},
}
nodes = append(nodes, bSdkStartup.NewStartupConfig()...)
reg := xReg.Register(context.Background(), nodes)
// 挂载所有 SDK 路由
sdkRoute := bSdkRoute.NewRoute(reg.Init.Ctx)
// OAuth2 路由(登录/回调/登出)
sdkRoute.OAuthRouter(reg.Serve.Group("/api"))
// 账户路由(注册/登录/刷新)
sdkRoute.AccountRouter(reg.Serve.Group("/api"))
// 用户路由(获取用户信息)
sdkRoute.UserRouter(reg.Serve.Group("/api"))
// 启动服务
_ = reg.Serve.Run(":8080")
}
```
# Token 管理 (/docs/beacon-sso/go-sdk/oauth2/token)
Token 管理 [#token-管理]
本文档介绍 Token 的缓存机制、刷新策略和注销流程。
Token 结构 [#token-结构]
SDK 使用 `CacheOAuthToken` 模型存储 Token 信息:
```go
type CacheOAuthToken struct {
AccessToken string // 访问令牌
TokenType string // 令牌类型(通常为 "Bearer")
RefreshToken string // 刷新令牌
Expiry string // 过期时间(RFC3339 格式)
}
```
缓存策略 [#缓存策略]
| 缓存类型 | Redis Key 模板 | TTL |
| ----------- | --------------------------- | ---- |
| OAuth Token | `oauth:token:{accessToken}` | 30 天 |
缓存时机 [#缓存时机]
Token 在以下情况下会被缓存:
1. **Exchange 成功后** - 授权码换取 Token 时自动缓存
2. **TokenSource 刷新后** - 刷新 Token 时更新缓存
3. **PasswordLogin 成功后** - 密码登录时自动缓存
Token 刷新 [#token-刷新]
TokenSource 方法 [#tokensource-方法]
```go
func (l *OAuthLogic) TokenSource(
ctx context.Context,
cacheToken *bSdkModels.CacheOAuthToken,
rt string,
) (*oauth2.Token, *xError.Error)
```
使用 Refresh Token 获取新的 Access Token。
**安全检查:**
* 验证传入的 RT 与缓存中的 RT 是否一致
* 不一致时清理缓存并返回错误
**使用示例:**
```go
oauthLogic := bSdkLogic.NewOAuth(ctx)
// 从缓存获取 Token
cacheToken, err := oauthLogic.GetToken(ctx, accessToken)
if err != nil {
// Token 不存在
return
}
// 刷新 Token
newToken, err := oauthLogic.TokenSource(ctx, cacheToken, refreshToken)
if err != nil {
// 刷新失败
return
}
```
自动刷新 [#自动刷新]
SDK 在路由层提供了 `/api/account/token/refresh` 接口,可以直接调用:
```bash
POST /api/account/token/refresh
Content-Type: application/json
{
"refresh_token": "your-refresh-token"
}
```
Token 获取 [#token-获取]
GetToken 方法 [#gettoken-方法]
```go
func (l *OAuthLogic) GetToken(ctx context.Context, accessToken string) (*bSdkModels.CacheOAuthToken, *xError.Error)
```
从 Redis 缓存中获取 Token 信息。
**用途:** 中间件验证用户身份时使用
Token 过期验证 [#token-过期验证]
VerifyExpiry 方法 [#verifyexpiry-方法]
```go
func (l *OAuthLogic) VerifyExpiry(ctx context.Context, accessToken string) (bool, *xError.Error)
```
检查 Token 是否已过期。
**返回值:**
* `true` - Token 已过期
* `false` - Token 未过期
**使用示例:**
```go
oauthLogic := bSdkLogic.NewOAuth(ctx)
isExpired, err := oauthLogic.VerifyExpiry(ctx, accessToken)
if err != nil {
// 获取 Token 失败
return
}
if isExpired {
// Token 已过期,需要刷新
}
```
Token 注销 [#token-注销]
Logout 方法 [#logout-方法]
```go
func (l *OAuthLogic) Logout(ctx context.Context, tokenType string, token string) *xError.Error
```
调用 OAuth2 Revocation Endpoint 注销 Token(符合 RFC 7009 规范)。
**参数:**
* `tokenType` - 令牌类型提示(`access_token` 或 `refresh_token`)
* `token` - 待注销的令牌值
**流程:**
1. 向 Revocation Endpoint 发送注销请求
2. 尝试清理本地 Redis 缓存
3. 缓存清理失败仅记录警告,不阻断流程
**使用示例:**
```go
oauthLogic := bSdkLogic.NewOAuth(ctx)
// 注销 Access Token
err := oauthLogic.Logout(ctx, "access_token", accessToken)
if err != nil {
// 注销失败
}
// 注销 Refresh Token
err = oauthLogic.Logout(ctx, "refresh_token", refreshToken)
```
HTTP 路由 [#http-路由]
SDK 提供以下 Token 相关路由:
| 方法 | 路径 | 说明 |
| ---- | ---------------------------- | --------------------- |
| POST | `/api/oauth/logout` | 注销 Token(从 Header 获取) |
| POST | `/api/account/token/refresh` | 刷新令牌 |
| POST | `/api/account/token/revoke` | 注销令牌(需认证) |
注销请求示例 [#注销请求示例]
```bash
# 从 Header 获取 Token 注销
POST /api/oauth/logout
Authorization: Bearer your-access-token
# 或者指定 Token 类型
POST /api/account/token/revoke
Authorization: Bearer your-access-token
Content-Type: application/json
{
"token_type_hint": "access_token"
}
```
# 缓存策略 (/docs/beacon-sso/java-sdk/advanced/cache)
缓存策略 [#缓存策略]
SDK 使用 Caffeine 进行高性能内存缓存,以提升性能和减少对 SSO Server 的请求。
缓存架构 [#缓存架构]
缓存配置 [#缓存配置]
SDK 内置 6 个缓存实例,每个缓存有不同的用途和 TTL 配置:
缓存列表 [#缓存列表]
| 缓存名称 | 说明 | TTL | 最大容量 |
| ------------------- | ---------------------------- | ----- | ------ |
| `oauthState` | OAuth2 State + PKCE Verifier | 15 分钟 | 10,000 |
| `grpcUserinfo` | gRPC 用户信息 | 10 秒 | 10,000 |
| `grpcMerchantTag` | 商户标签 | 10 秒 | 10,000 |
| `grpcAnnouncement` | 公告信息 | 10 秒 | 10,000 |
| `httpUserinfo` | HTTP 用户信息 | 10 秒 | 10,000 |
| `httpIntrospection` | Token 自省结果 | 10 秒 | 10,000 |
缓存 Bean 名为 `beaconSsoCacheManager`,基于 Spring 的 `CaffeineCacheManager` 实现。所有缓存在应用重启后会自动失效。
与 Go SDK 的对比 [#与-go-sdk-的对比]
Java SDK 使用 **Caffeine**(进程内内存缓存),Go SDK 使用 **Redis**(分布式缓存)。两者的缓存策略有本质区别:
| 对比项 | Java SDK (Caffeine) | Go SDK (Redis) |
| ----- | ------------------- | -------------- |
| 存储位置 | JVM 进程内内存 | Redis 服务 |
| 分布式支持 | 不支持(单实例) | 支持(跨实例共享) |
| 缓存失效 | 进程重启即失效 | 基于 TTL 过期 |
| 外部依赖 | 无 | 需要 Redis |
| 数据一致性 | 各实例独立缓存 | 多实例共享同一份缓存 |
影响说明 [#影响说明]
* **无分布式缓存失效**:各应用实例拥有独立的缓存副本,某个实例缓存的数据变更不会自动同步到其他实例
* **适用场景**:适合单实例部署或无状态部署(如 K8s Pod),每个实例独立维护缓存
* **TTL 较短**:大部分缓存 TTL 为 10 秒,确保数据不会长期不一致
OAuthState 实体 [#oauthstate-实体]
OAuth2 流程中用于存储 State 和 PKCE 信息的缓存实体:
| 字段 | 类型 | 说明 |
| -------------- | ------- | ------------------ |
| `state` | String | 随机状态码 |
| `codeVerifier` | String | PKCE Code Verifier |
| `redirectUri` | String | 回调地址 |
| `createdAt` | Instant | 创建时间 |
| `expiresAt` | Instant | 过期时间 |
方法 [#方法]
| 方法 | 返回值 | 说明 |
| ------------- | --------- | ------------------- |
| `isExpired()` | `boolean` | 判断 OAuthState 是否已过期 |
# 高级话题 (/docs/beacon-sso/java-sdk/advanced)
高级话题 [#高级话题]
本章节介绍 SDK 的高级配置和使用技巧。
子文档 [#子文档]
了解 SDK 的 Caffeine 内存缓存机制和配置选项
直接使用 SsoApi [#直接使用-ssoapi]
除了通过 Filter 和 AOP 的方式使用 SDK 外,你还可以直接注入 `SsoApi` Bean 进行编程式调用:
```java
@RestController
@RequestMapping("/api")
public class DemoController {
private final SsoApi ssoApi;
public DemoController(SsoApi ssoApi) {
this.ssoApi = ssoApi;
}
@GetMapping("/userinfo")
public BaseResponse getUserinfo(HttpServletRequest request) {
String token = SsoSecurityUtil.getCurrentToken(request).orElse(null);
UserinfoResult result = ssoApi.user().getCurrentUser(token);
return BaseResponse.success("获取成功", result);
}
}
```
传输模式 [#传输模式]
HTTP-only 模式(默认) [#http-only-模式默认]
SDK 默认仅使用 HTTP 传输,适用于只需要 OAuth2 登录流程和 Token 自省的场景。无需额外配置 gRPC 参数。
gRPC 模式 [#grpc-模式]
启用 gRPC 后,SDK 会同时使用 HTTP(OAuth2 流程)和 gRPC(用户、认证、商户服务)两种传输方式:
```yaml
beacon:
sso:
grpc:
enabled: true
host: sso.example.com
port: 5566
app-access-id: app-xxx
app-secret-key: secret-xxx
```
OAuth2 授权流程始终使用 HTTP 传输,gRPC 仅用于用户信息、账户管理和商户服务等内部服务调用。
# AOP 切面 (/docs/beacon-sso/java-sdk/aop)
AOP 切面 [#aop-切面]
SDK 提供 Spring AOP 注解,用于在 Controller 方法执行前进行参数注入和权限验证。
可用注解 [#可用注解]
| 注解 | 说明 |
| ---------------------------------------- | ------------------------- |
| [@InjectData](./inject-data) | 自动注入用户数据到 Controller 方法参数 |
| [@PermissionVerify](./permission-verify) | 基于 scope 的权限验证 |
前置条件 [#前置条件]
AOP 切面依赖 `BeaconSsoFilter` 先完成 Token 认证。过滤器会将 `IntrospectResult` 存入 Request Attribute,AOP 切面再从中读取数据进行注入或权限校验。
请确保 `BeaconSsoFilter` 已正确配置且处于启用状态,否则 AOP 注解将无法获取到用户认证信息。
子文档 [#子文档]
自动注入 IntrospectResult 字段到 Controller 方法参数
基于 scope 的方法级权限验证
# @InjectData (/docs/beacon-sso/java-sdk/aop/inject-data)
@InjectData [#injectdata]
`@InjectData` 注解用于自动将 `IntrospectResult` 中的字段注入到 Controller 方法参数中,简化获取用户信息的代码。
功能说明 [#功能说明]
通过 `@InjectData` 注解,你可以直接在 Controller 方法参数上声明需要的用户数据字段,SDK 会自动从 `BeaconSsoFilter` 存入的 `IntrospectResult` 中提取对应值并注入。
支持的字段 [#支持的字段]
| 字段 | 类型 | 说明 |
| ----------- | ------- | -------------- |
| `sub` | String | 用户唯一标识 |
| `username` | String | 用户名 |
| `clientId` | String | 客户端 ID |
| `scope` | String | 权限范围 |
| `tokenType` | String | 令牌类型 |
| `iss` | String | 签发者 |
| `jti` | String | 令牌 ID |
| `exp` | Long | 过期时间(Unix 时间戳) |
| `iat` | Long | 签发时间(Unix 时间戳) |
| `nbf` | Long | 生效时间(Unix 时间戳) |
| `aud` | String | 受众 |
| `active` | Boolean | 令牌是否有效 |
类型转换 [#类型转换]
SDK 支持以下类型自动转换:
| 目标类型 | 转换规则 |
| -------------- | --------------------------- |
| `String` | 直接取值 |
| `Boolean` | 字符串转布尔值 |
| `Long` | 字符串转长整型(适用于时间戳字段) |
| `List` | 逗号分隔的字符串转为列表(适用于 scope 等字段) |
注入整个 IntrospectResult [#注入整个-introspectresult]
如果不指定 `value()` 且参数类型为 `IntrospectResult`,SDK 会注入完整的自省结果对象。
使用示例 [#使用示例]
```java
@RestController
@RequestMapping("/api")
public class DemoController {
// 注入单个字段
@GetMapping("/profile")
public BaseResponse getProfile(@InjectData("sub") String userId) {
return BaseResponse.success("获取成功", userId);
}
// 注入完整对象
@GetMapping("/info")
public BaseResponse getInfo(@InjectData IntrospectResult result) {
return BaseResponse.success("获取成功", result);
}
// 注入多个字段
@GetMapping("/detail")
public BaseResponse