SDK 集成(Go)
Passport Go SDK 基于 Gin 框架设计,提供中间件和工具函数,帮助 Go 应用快速集成 Passport 的认证鉴权功能。
版本说明(重要)
本章基于
github.com/vancone/vancone-passport-sdk-go的develop分支(e7e27d0,2026-02-08)。该仓库当前尚未发布与本章 API 对应的正式版本:
- 默认分支
main仍停留在初始提交,不包含 SDK 代码。- 已发布的 tag
v0.1.0.20250805.1(2025-08-05)是早期版本,其 API 与本章不兼容(入口函数、包路径、配置键名均不同)。因此请勿使用不带版本约束的
go get,请按 Step 1 显式指定develop分支,或等待正式版本发布后按发版说明锁定版本号。
快速开始
Step 1:安装 SDK
go get github.com/vancone/vancone-passport-sdk-go@develop
SDK 的间接依赖(无需手动引入):github.com/gin-gonic/gin、github.com/spf13/viper、github.com/golang-jwt/jwt/v5。要求 Go 1.21.3 及以上。
Step 2:修改配置文件
在 config.yaml 或 config.yml 中添加以下配置:
passport:
# 平台配置
platform:
base-url: https://passport.vancone.com # Passport 平台地址
# Token 配置
token:
public-key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE... # Base64 编码的公钥
# 认证配置
authentication:
enabled: true # 是否开启登录认证
uri-allowlist: # 不需要登录认证的 URI 列表
- /api/v1/public/**
- /health
# 应用账号配置(仅在调用 Passport 接口时需要)
app-account:
ak: AKIDxxxxxxxxxxxxxxxx # Access Key ID
sk: xxxxxxxxxxxxxxxxxxx # Secret Access Key
配置说明:
| 配置项 | 必填 | 默认值 | 说明 |
|---|---|---|---|
platform.base-url | 否 | https://passport.vancone.com | Passport 平台地址,SDK 调用平台接口时的前缀 |
token.public-key | 是 | - | 用于校验 Token 的公钥(Base64 编码的 PKIX 公钥) |
authentication.enabled | 否 | true | 是否开启登录认证;置为 false 时中间件直接放行所有请求 |
authentication.uri-allowlist | 否 | - | 不需要登录认证的 URI 模式列表,支持路径模式匹配(见「路径模式」) |
app-account.ak | 否 | - | 应用账号的 Access Key ID,仅在调用 ApplyToken / RequestWithAuth / Request(auth=true) 时需要 |
app-account.sk | 否 | - | 应用账号的 Secret Access Key,同上 |
当前版本未生效的配置项(配置结构体中存在,但实现尚未使用,配置后不会产生任何效果):
| 配置项 | 状态 |
|---|---|
platform.cache-sync-seconds | 预留字段。Token 缓存周期固定为 3600 秒,不可配置 |
token.algorithm | 预留字段。SDK 仅支持 ES256,非 ECDSA 签名的 Token 一律校验失败 |
access-control.enabled | 预留字段。权限校验尚未实现,见「权限校验」 |
access-control.uri-allowlist | 同上 |
csrf.enabled / csrf.secret-key | 预留字段,尚未实现 |
Step 3:初始化 SDK
package main
import (
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"github.com/vancone/vancone-passport-sdk-go/pkg/config"
"github.com/vancone/vancone-passport-sdk-go/pkg/middleware"
)
func main() {
// 读取配置
viper.SetConfigFile("config.yaml")
if err := viper.ReadInConfig(); err != nil {
panic(err)
}
// 初始化 SDK(必须在注册中间件之前调用)
config.Init(viper.GetViper())
r := gin.Default()
// 添加认证中间件
r.Use(middleware.AuthMiddleware)
r.Run(":8080")
}
注意:
AuthMiddleware位于pkg/middleware包,而不是pkg/config包。pkg/config只负责配置读取,不导出任何中间件。
Step 4:使用 SDK 工具
获取当前用户信息
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/vancone/vancone-passport-sdk-go/pkg/util"
)
func GetUser(ctx *gin.Context) {
// 获取完整的账号信息
accountInfo := util.GetAccountInfo(ctx)
if accountInfo != nil {
fmt.Printf("AccountId: %s\n", accountInfo.AccountId)
fmt.Printf("TenantId: %s\n", accountInfo.TenantId)
fmt.Printf("UserId: %s\n", accountInfo.UserId)
}
// 获取单个信息
tenantId := util.GetTenantId(ctx)
accountId := util.GetAccountId(ctx)
userId := util.GetUserId(ctx)
fmt.Println(tenantId, accountId, userId)
}
AccountInfo 结构体定义:
| 字段 | 类型 | 说明 |
|---|---|---|
tenantId | string | 租户 ID |
accountId | string | 账号 ID |
userId | string | 用户 ID(登录名) |
permissionIds | []string | 权限 ID 列表。当前版本不会填充该字段,值恒为空 |
若需要权限信息,请通过 Passport 开放接口自行查询,不要依赖
permissionIds字段。
获取应用账号 Token
import (
"github.com/vancone/vancone-passport-sdk-go/pkg/util"
)
func GetAppToken() string {
// 自动获取或刷新应用账号 Token(内部缓存 3600 秒)
token := util.ApplyToken()
return token
}
ApplyToken 使用 app-account.ak / app-account.sk 向 Passport 平台换取 Token,流程为:
POST {base-url}/api/passport/service/v1/token/signature,请求体{"accessKeyId": "...", "secretAccessKey": "..."},返回{"timestamp": "...", "signature": "..."}POST {base-url}/api/passport/service/v1/token,请求体{"accessKeyId": "...", "timestamp": "...", "signature": "..."},返回 Token 字符串
风险提示:若
ak/sk配置错误或应用账号无权限,平台返回的data为null,此时ApplyToken会抛出 panic。请确保在生产环境中正确配置ak/sk,并对调用方做好恢复处理。
发起认证请求
import (
"github.com/vancone/vancone-passport-sdk-go/pkg/util"
)
func CallPassportAPI() {
// 使用 SDK 的 HTTP 工具发送请求(自动携带应用账号 Token)
resp := util.Request("https://passport.vancone.com/api/passport/service/v1/account", "GET", "", true)
fmt.Println(string(resp))
// 等价于 Request(uri, method, body, true)
resp2 := util.RequestWithAuth("https://passport.vancone.com/api/passport/service/v1/account", "GET", "")
fmt.Println(string(resp2))
}
HTTP 工具函数:
| 函数 | 说明 |
|---|---|
util.Request(uri, method, body string, auth bool) []byte | 发起 HTTP 请求。auth 为 true 时自动在 passport-token 请求头中携带 ApplyToken() 获取的 Token。出错时返回 nil |
util.RequestWithAuth(uri, method, body string) []byte | 等价于 Request(uri, method, body, true) |
中间件说明
middleware.AuthMiddleware 的处理流程:
- 开关判断:若
authentication.enabled为false,直接放行所有请求。 - 白名单匹配:请求路径命中
authentication.uri-allowlist中的任一模式时放行,不做 Token 校验。 - 读取 Token:优先从 Cookie
passport_token读取;Cookie 为空时,从请求头passport-token读取。 - 校验 Token:使用配置中的公钥校验 ES256 签名,并校验有效期。
- 注入用户信息:校验通过后,将账号信息写入 Gin Context;校验失败则中断请求并返回 HTTP 401。
Token 的传递方式(前后端对接时需要对齐):
| 位置 | 名称 |
|---|---|
| Cookie | passport_token |
| 请求头 | passport-token |
鉴权失败的响应:当前版本中间件调用
AbortWithStatus(401)中断请求,响应体为空。如需与平台统一的错误格式({"code": 11002, "message": "Not authorized"})保持一致,请在业务侧自行追加一个错误处理中间件构造响应体。
Context 中可用的信息
通过中间件后,可以在 Handler 中通过 Gin Context 获取以下信息:
| Key 常量 | Key 实际值 | 类型 | 说明 |
|---|---|---|---|
constant.TokenKeyAccountId | acid | string | 账号 ID |
constant.TokenKeyTenantId | tid | string | 租户 ID |
constant.TokenKeyUserId | uid | string | 用户 ID(登录名) |
constant.AccountInfo | accountInfo | model.AccountInfo(值类型,非指针) | 完整账号信息 |
推荐通过 util.GetAccountInfo / util.GetTenantId 等工具函数读取,避免直接断言类型。若确实需要直接读取:
accountInfo := ctx.MustGet(constant.AccountInfo).(model.AccountInfo) // 注意是值类型
路径模式
authentication.uri-allowlist 支持以下三种模式:
| 路径模式 | 说明 | 优先级 |
|---|---|---|
/users/{id} | 精确匹配,支持路径变量 | 高 |
/users/* | 单段通配,匹配一层路径 | 中 |
/api/** | 多段通配,匹配任意层级(含零层) | 低 |
SDK 会按优先级从高到低排序,自动匹配最佳模式。匹配前会对模式与请求路径做规范化处理(合并重复斜杠、补全前导斜杠、去除末尾斜杠)。
权限校验
当前版本尚未实现。
access-control相关配置(见 Step 2)在配置结构体中存在,但中间件不会读取,配置后不会生效。
如需进行权限校验,请通过 Passport 开放接口在业务侧自行实现。SDK 提供的路径模式匹配能力(pkg/util/path_parser.go)可用于白名单场景。
示例:完整的用户控制器
package controller
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/vancone/vancone-passport-sdk-go/pkg/constant"
"github.com/vancone/vancone-passport-sdk-go/pkg/model"
"github.com/vancone/vancone-passport-sdk-go/pkg/util"
)
type UserController struct{}
// GetUser 获取当前用户信息
func (c *UserController) GetUser(ctx *gin.Context) {
accountInfo := util.GetAccountInfo(ctx)
if accountInfo == nil {
ctx.JSON(http.StatusUnauthorized, gin.H{"message": "Not authorized"})
return
}
ctx.JSON(http.StatusOK, gin.H{
"accountId": accountInfo.AccountId,
"userId": accountInfo.UserId,
"tenantId": accountInfo.TenantId,
})
}
// GetCurrentUserProfile 调用 Passport 平台获取用户资料
func (c *UserController) GetCurrentUserProfile(ctx *gin.Context) {
resp := util.RequestWithAuth(
"https://passport.vancone.com/api/passport/service/v1/account-profile", "GET", "")
ctx.Data(http.StatusOK, "application/json", resp)
}
// ReadRawAccountInfo 直接读取 Context(不推荐,注意是值类型)
func (c *UserController) ReadRawAccountInfo(ctx *gin.Context) {
accountInfo := ctx.MustGet(constant.AccountInfo).(model.AccountInfo)
ctx.JSON(http.StatusOK, accountInfo)
}
配置示例
最小配置(仅认证)
passport:
token:
public-key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
完整配置(认证 + 平台调用)
passport:
platform:
base-url: https://passport.vancone.com
token:
public-key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
app-account:
ak: AKIDxxxxxxxxxxxxxxxx
sk: xxxxxxxxxxxxxxxxxxx
authentication:
enabled: true
uri-allowlist:
- /api/v1/public/**
- /health
注意事项
- 公钥获取:公钥为 Base64 编码的 PKIX 公钥(ES256)。请从 Passport 部署方获取,并妥善保管;公钥变更会导致所有 Token 校验失败。
- 安装版本:务必指定
@develop或正式版本号,不带版本约束的go get会安装到 API 不兼容的旧版本。 - 初始化顺序:
config.Init()必须在注册middleware.AuthMiddleware之前调用,否则公钥与白名单均无法加载。 - URI 白名单:不需要认证的接口(如健康检查、公开查询)应添加到
authentication.uri-allowlist。 - 算法支持:当前版本仅支持 ES256,非 ECDSA 签名的 Token 会被直接拒绝。
- 权限校验:尚未实现,不要在业务中依赖
access-control配置或PermissionIds字段。
SDK 架构说明
| 模块 | 文件路径 | 说明 |
|---|---|---|
| 配置管理 | pkg/config/config.go | 使用 Viper 读取配置,提供默认值 |
| 中间件 | pkg/middleware/middleware.go | Token 验证、用户信息注入、URI 白名单 |
| Token 工具 | pkg/util/token.go | 应用账号 Token 申请与缓存、Token 校验、解析账号信息 |
| HTTP 工具 | pkg/util/http_util.go | 发起 HTTP 请求,可选自动携带 Token |
| 路径解析 | pkg/util/path_parser.go | 路径模式匹配 |
| 账号工具 | pkg/util/account_util.go | 从 Context 获取用户信息 |
| 模型定义 | pkg/model/account_info.go | AccountInfo 结构体 |
| 常量定义 | pkg/constant/constant.go | Cookie Key、Header Key、Token Key 定义 |
导出函数一览
| 函数 | 签名 | 说明 |
|---|---|---|
config.Init | Init(viper *viper.Viper) | 初始化 SDK 配置 |
middleware.AuthMiddleware | func(ctx *gin.Context) | 认证中间件 |
middleware.Authenticate | func(ctx *gin.Context) bool | 认证逻辑,可直接调用 |
util.GetAccountInfo | (ctx *gin.Context) *model.AccountInfo | 获取完整账号信息 |
util.GetTenantId | (ctx *gin.Context) string | 获取租户 ID |
util.GetAccountId | (ctx *gin.Context) string | 获取账号 ID |
util.GetUserId | (ctx *gin.Context) string | 获取用户 ID |
util.GetToken | (ctx *gin.Context) string | 从请求中获取用户 Token |
util.ApplyToken | () string | 获取应用账号 Token(内部缓存 3600 秒) |
util.ValidateToken | (tokenStr string) bool | 校验 Token 签名与有效期 |
util.ParseAccountInfo | (tokenStr string) model.AccountInfo | 解析 Token 中的账号信息 |
util.InitKeys | () | 显式初始化公钥(通常由校验函数自动调用) |
util.Request | (uri, method, body string, auth bool) []byte | 发起 HTTP 请求 |
util.RequestWithAuth | (uri, method, body string) []byte | 发起携带应用 Token 的 HTTP 请求 |
util.NewPathPatternParser | () *PathPatternParser | 创建路径模式解析器 |
API 对比
| 功能 | Java SDK | Go SDK |
|---|---|---|
| 框架 | Spring Boot | Gin |
| 配置方式 | @ConfigurationProperties + @EnableConfigurationProperties | Viper + YAML 配置文件 |
| 中间件 | Servlet Filter | Gin Middleware |
| Token 验证 | JJWT | golang-jwt/jwt |
| Token 传递 | Cookie + Header | Cookie passport_token + Header passport-token |
| Token 算法 | ES256 | ES256 |
| 路径匹配 | Spring AntPathMatcher | 自定义路径模式解析(pkg/util/path_parser.go) |
| 权限校验 | 支持 | 尚未实现 |