公开接口

Passport 提供了一套完整的 REST API,供开发者在任意语言或框架的应用中调用,实现认证鉴权功能。

本文档以 passport-service 的路由注册(internal/router/router.go)为基准编写,所有接口路径、参数与响应结构均取自当前实现。

Base URL

根据部署环境选择:

# 生产环境
https://passport.vancone.com

# 测试环境(仅限内网访问)
http://passport.beta.vancone.com

所有接口统一前缀为 /api/passport/service/v1

请求说明

认证方式

Token 通过以下两种方式之一传递,服务端优先读取 Cookie:

方式名称
Cookiepassport_token
请求头passport-token

登录成功后,服务端会同时下发两个 Cookie:passport_token(Token)与 passport_username(用户名或登录名)。

需要认证的接口

服务端按 passport.filter.url-patterns 配置对匹配的路由做 Token 校验,未匹配的路径不做校验。默认需要携带 Token 的接口为:

路径说明
/api/passport/service/v1/account账号查询、更新(创建 POST 除外
/api/passport/service/v1/account/*登录历史、找回密码等子路径
/api/passport/service/v1/account-profile用户资料
/api/passport/service/v1/account-profile/*头像
/api/passport/service/v1/sync/*同步接口
/api/passport/service/v1/query/*分页查询

显式的免校验规则(代码硬编码,不受配置影响):

  • POST /api/passport/service/v1/account(账号注册)
  • /api/passport/service/v1/account/forgot-password/*(找回密码全流程)

请求体格式

除「验证滑块验证码」接口使用 application/x-www-form-urlencoded 外,其余接口请求与响应均为 JSON 格式。

响应格式

所有响应遵循统一格式:

{
  "code": 0,
  "message": "success",
  "data": { ... }
}
字段说明
code业务状态码,0 表示成功,其他值表示失败
message响应消息
data响应数据,无数据时该字段被省略

HTTP 状态码与业务状态码是两套独立的东西,请务必区分

HTTP 状态码业务 code出现场景
2000成功
200100011000540014006登录失败、找回密码失败。业务错误仍返回 200,必须解析 body 中的 code 判断
200 / 500-1服务端异常、参数绑定失败等兜底错误
40111002Token 缺失或无效
403403越权(例如尝试更新他人账号)
404-资源不存在(如无头像时获取头像)

API 列表

Login 模块

1.1 用户登录

GET  /api/passport/service/v1/login
POST /api/passport/service/v1/login

登录必须先通过滑块验证码(见 8.2、8.3),否则会返回 10005

请求参数(GET 走 query,POST 走 JSON body):

参数类型必填说明
userIdstring登录名。与 email 二选一,二者同时为空时按空账号处理
emailstring邮箱。userId 为空时作为登录标识
passwordstring密码明文,服务端以 BCrypt 比对
captchaTokenstring滑块验证码校验通过后返回的票据
tenantIdstring租户 ID

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
    "username": "admin"
  }
}

响应中只有 tokenusername 两个字段。username 取账号的 name,未设置 name 时回退为 userId

业务结果:登录成功时同时下发 passport_tokenpassport_username 两个 Cookie,有效期由服务端配置 passport.cookie.expired-seconds 决定(默认 86400 秒)。

锁定策略:连续登录失败次数超过服务端配置 passport.login-failure-times-limit(默认 5)后,账号被锁定,返回 10003;登录成功后失败计数清零。

失败响应(HTTP 200):

{
  "code": 10002,
  "message": "Incorrect password"
}

1.2 登出

DELETE /api/passport/service/v1/login

响应

{
  "code": 0,
  "message": "success"
}

说明:清除 passport_tokenpassport_username 两个 Cookie。服务端为无状态 JWT,不维护会话黑名单,登出仅清除客户端 Cookie。

App 登出:请求体可携带 { "refreshToken": "..." },服务端会删除对应的 refresh token 记录实现服务端吊销;Web 端不带请求体,行为不变。

1.3 App 登录(桌面 / 移动端)

POST /api/passport/service/v1/login/app

供原生 App(Electron 桌面端、Android)使用的独立登录端点。与 Web 登录(1.1)的区别:

  • 不种 Cookie,Token 由客户端自行安全存储;
  • 响应额外返回 refreshToken(有效期 30 天),用于静默续期(见 2.5);
  • 登录历史中的 clientType 记录客户端类型。

请求体:

参数类型必填说明
userIdstring登录名。与 email 二选一
emailstring邮箱
passwordstring密码明文
captchaTokenstring滑块验证码票据(见 8.3),App 端同样必须过滑块
tenantIdstring租户 ID
clientTypestring客户端类型:DESKTOP / ANDROID,缺省 APP

响应:

{
  "code": 0,
  "message": "success",
  "data": {
    "token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
    "username": "admin",
    "refreshToken": "kN9xQ2p...43位URL安全随机串"
  }
}

失败语义与 1.1 完全一致(HTTP 200 + 业务码 10001~10005)。

设计说明:App 登录与 Web 登录是两个独立端点(逻辑同一套,契约分开)——Token 生命周期、安全策略、后续废弃节奏(迁移 OIDC PKCE)都按客户端独立演进。

1.4 扫码登录

扫码登录(Web 展示二维码 + 扫码设备确认)包含创建会话、轮询状态、上报扫码、确认登录四个接口,已独立成文,见「扫码登录接入」


Token 模块

2.1 生成签名

应用账号换取 Token 的第一步。

POST /api/passport/service/v1/token/signature

请求体

参数类型必填说明
accessKeyIdstring应用账号的 Access Key ID
secretAccessKeystring应用账号的 Secret Access Key

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "signature": "ABCDEF123456...",
    "timestamp": "1640000000000"
  }
}

签名计算方式(服务端实现,客户端调用本接口即可,无需自行计算):

timestamp = 当前毫秒时间戳
signature = UPPER(HEX(HMAC-SHA256(secretAccessKey, accessKeyId + timestamp)))

2.2 生成 Token

POST /api/passport/service/v1/token

请求体

参数类型必填说明
accessKeyIdstringAccess Key ID
timestampstring上一步返回的毫秒时间戳
signaturestring上一步返回的签名

响应dataToken 字符串(不是对象)。

{
  "code": 0,
  "message": "success",
  "data": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
}

签名校验失败时返回 HTTP 500、code-1messagesignature validation failed

2.3 验证 Token

POST /api/passport/service/v1/token/validate

请求体

参数类型必填说明
tokenstring要验证的 Token

响应data布尔值

{
  "code": 0,
  "message": "success",
  "data": true
}

2.4 获取 Token 剩余有效期

POST /api/passport/service/v1/token/expiration

请求体

参数类型必填说明
tokenstring要查询的 Token

响应data剩余秒数(整数)。

{
  "code": 0,
  "message": "success",
  "data": 86399
}

说明:Token 无效或已过期时返回 0。Token 有效期固定为签发后 24 小时,不支持续期,过期后需重新登录或重新申请。

2.5 刷新 Token(App)

POST /api/passport/service/v1/token/refresh

使用 1.3 返回的 refreshToken 换取新的 access token 与新的 refresh token。旋转式:旧 refreshToken 在本次调用中被消费,立即作废。

请求体:

参数类型必填说明
refreshTokenstring1.3 或上次刷新返回的 refreshToken

响应:

{
  "code": 0,
  "message": "success",
  "data": {
    "token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "新的refreshToken"
  }
}

说明:

  • 新 access token 按服务端存储的账号重新签发,权限变更在刷新后即时生效;
  • refreshToken 无效或已过期返回 HTTP 401 / code 11002,客户端应回到登录页;
  • 该接口免滑块:refreshToken 本身即凭证;
  • 登出时携带 refreshToken 调用 DELETE /login 可在服务端吊销(见 1.2)。

Token 结构

Token 为 ES256 签名的 JWT,Claims 如下:

Claim说明
acid账号 ID
uid用户 ID(登录名)
tid租户 ID
pids权限 ID 数组
exp过期时间(签发时间 + 24 小时)

Account 模块

3.1 查询当前账号信息

GET /api/passport/service/v1/account

需要携带 Token。返回的是 Token 中 acid 对应的账号。

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "1234567890",
    "userId": "user123",
    "type": "PERSONAL",
    "name": "张三",
    "email": "user@example.com",
    "phone": "13800138000",
    "tenantId": "0",
    "applicationId": ""
  }
}

字段说明:

字段说明
id账号 ID(雪花 ID),即 Token 中的 acid 声明
userId登录名
type账号类型:PERSONAL(个人账号)或 SERVICE(应用账号)
name账号名称
email / phone邮箱、手机号,为空时字段被省略
tenantId租户 ID
applicationId所属应用 ID,仅应用账号有值
loginFailureCount连续登录失败次数,为 0 时字段被省略
  • 出于安全考虑,响应中不包含 password 字段。
  • lastLoginTimebirthDayapplicationName 为派生字段,当前实现不会填充,响应中不会出现。生日信息请通过「用户资料」接口获取(见 4.1,字段名为 birthday)。

3.2 创建账号(注册)

POST /api/passport/service/v1/account

该接口免 Token 校验。

请求体

参数类型必填说明
userIdstring登录名
typestring账号类型:PERSONALSERVICE
namestring账号名称
passwordstring密码。个人账号建议必填
emailstring邮箱地址
phonestring手机号码
applicationIdstring所属应用 ID,仅应用账号需要

响应:与 3.1 相同的账号对象。

说明:当前版本注册不需要邮箱验证码,注册完成即可登录,账号没有「待激活」状态。密码复杂度仅由前端校验,服务端未做强制约束,接入方如需约束请自行在业务侧实现。

3.3 更新账号

PUT /api/passport/service/v1/account

需要携带 Token。

请求体

参数类型必填说明
idstring账号 ID,必须与 Token 中的 acid 一致,否则返回 403
namestring账号名称
emailstring邮箱地址,找回密码时使用
phonestring手机号码

响应

{
  "code": 0,
  "message": "success"
}

重要警告:该接口采用全量保存。请求体中不要携带 password 字段——若携带,提交的明文会直接覆盖数据库中的 BCrypt 密文,导致该账号永久无法登录。当前版本没有提供修改密码接口,修改密码请走「找回密码」流程(见 9.1–9.3)。


Account Profile 模块

4.1 查询用户资料

GET /api/passport/service/v1/account-profile

需要携带 Token。

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "1234567890",
    "name": "张三",
    "gender": "MALE",
    "birthday": "1990-01-01",
    "bio": "这是一段个人简介",
    "avatar": "/api/passport/service/v1/account-profile/avatar",
    "updatedTime": "2024-01-01 10:00:00"
  }
}
字段说明
id账号 ID,与账号的 id 相同
name姓名
gender性别:MALE / FEMALE / OTHERS
birthday生日
bio个人简介
avatar头像访问路径。已上传头像时为该固定路径,未上传时为空字符串
updatedTime更新时间

资料中不包含 emailphone,这两个字段属于账号(Account)而非资料(Profile)。

4.2 更新用户资料

PUT /api/passport/service/v1/account-profile

需要携带 Token。

请求体

参数类型必填说明
namestring姓名
genderstring性别:MALE / FEMALE / OTHERS
birthdaystring生日(格式:YYYY-MM-DD)
biostring个人简介

响应

{
  "code": 0,
  "message": "success"
}

说明:资料的 id 由服务端从 Token 中取,不读取请求体中的 id,因此无法修改他人资料。

4.3 获取头像

GET /api/passport/service/v1/account-profile/avatar

需要携带 Token。返回当前账号的头像图片二进制流。

未上传头像时返回 HTTP 404,且不返回 JSON 响应体。

4.4 上传头像

POST /api/passport/service/v1/account-profile/avatar

需要携带 Token。使用 multipart/form-data 上传。

请求参数

参数类型必填说明
filefile头像文件。仅支持 .jpg / .jpeg / .png / .gif

响应

{
  "code": 0,
  "message": "success",
  "data": "/api/passport/service/v1/account-profile/avatar"
}

说明:文件以「账号 ID + 原扩展名」命名,上传新头像会覆盖同账号的旧头像文件。


Query 模块

5.1 分页查询账号

GET /api/passport/service/v1/query/account

需要携带 Token。

请求参数

参数类型必填说明
pageNoint页码,默认 1
pageSizeint每页数量,默认 10
searchstring搜索关键字
accountIdstring指定账号 ID 查询

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "list": [
      {
        "id": "1234567890",
        "userId": "user123",
        "name": "张三"
      }
    ],
    "pageNo": 1,
    "pageSize": 10,
    "totalCount": 100,
    "totalPage": 10
  }
}

分页查询仅返回 iduserIdname 三个字段,不包含邮箱、手机号等信息。如需完整账号信息,请先按 id 调用 3.1 查询账号接口。

分页字段说明:

字段说明
list当前页数据
pageNo当前页码
pageSize每页数量
totalCount总记录数
totalPage总页数

Login History 模块

6.1 查询登录历史

GET /api/passport/service/v1/account/login-history

需要携带 Token。返回当前账号最近的登录记录。

响应

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "accountId": "1234567890",
      "clientIp": "192.168.1.1",
      "loginMethod": "WEB",
      "LoginTime": "2024-01-01 10:00:00"
    }
  ]
}
字段说明
accountId账号 ID
clientIp登录 IP
clientType客户端类型:DESKTOP / ANDROID / APP,Web 登录时该字段被省略
loginMethod登录方式:WEB(页面登录)、API(接口换取 Token)或 QR_CODE(扫码登录)
LoginTime登录时间。注意该字段的 JSON 键首字母为大写,与其他字段风格不一致,取值时请照此处理

Sync 模块

用于应用账号(SDK 接入方)同步自身应用下的 API 与权限定义。需要携带应用账号的 Token。

7.1 同步 API 列表

GET /api/passport/service/v1/sync/api

响应

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": "api123",
      "name": "查询用户",
      "path": "/api/user/*",
      "method": "GET",
      "description": "查询用户信息",
      "applicationId": "app123",
      "tenantId": "0",
      "creator": "admin",
      "updater": "admin",
      "createdTime": "2024-01-01 10:00:00",
      "updatedTime": "2024-01-01 10:00:00"
    }
  ]
}

说明:返回当前应用账号所属应用的 API 列表。若账号未绑定应用,返回空数组。

7.2 同步权限列表

GET /api/passport/service/v1/sync/permission

响应

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": "permission123",
      "name": "用户管理权限",
      "description": "用户管理相关权限",
      "applicationId": "app123",
      "applicationName": "用户服务",
      "riskLevel": "LOW",
      "apiCount": 5,
      "tenantId": "0",
      "creator": "admin",
      "updater": "admin",
      "createdTime": "2024-01-01 10:00:00",
      "updatedTime": "2024-01-01 10:00:00",
      "apiIds": ["api1", "api2", "api3", "api4", "api5"]
    }
  ]
}

说明:权限归属应用,字段为 applicationId / applicationName(早期版本中的 serviceId / serviceName 已废弃)。

7.3 同步标志

GET /api/passport/service/v1/sync/flag

该接口尚未实现,当前调用会返回 HTTP 500。请勿在生产环境依赖此接口。


Verify 模块

8.1 生成邮箱验证码

GET /api/passport/service/v1/verify?email=user@example.com

请求参数

参数类型必填说明
emailstring邮箱地址

响应datanull,验证码通过邮件发送。

{
  "code": 0,
  "message": "success"
}

8.2 生成滑块验证码

GET /api/passport/service/v1/verify/image

响应:返回滑块验证码素材,不是图片流

{
  "code": 0,
  "message": "success",
  "data": {
    "key": "captcha:xxxxxxxx",
    "imageBase64": "iVBORw0KGgoAAAANSUhEUg...",
    "tileBase64": "iVBORw0KGgoAAAANSUhEUg...",
    "tileWidth": 60,
    "tileHeight": 60,
    "tileX": 120,
    "tileY": 45
  }
}
字段说明
key验证码标识,提交校验时回传
imageBase64底图(Base64)
tileBase64滑块拼图块(Base64)
tileWidth / tileHeight拼图块尺寸
tileX / tileY拼图块在底图中的目标位置

出于安全考虑,tileX(缺口横坐标)由服务端返回,接入方据此渲染初始位置并采集用户拖动轨迹。

8.3 校验滑块验证码

POST /api/passport/service/v1/verify/image

该接口使用表单格式(application/x-www-form-urlencoded),不是 JSON。

请求参数

参数类型必填说明
pointstring用户拖动滑块的落点坐标,格式 "x,y",例如 "118,45"
keystring8.2 返回的 key

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "captchaToken": "captcha:token:xxxxxxxx",
    "ok": true
  }
}

说明:校验容差为 4 像素。okfalse 表示校验未通过,此时 captchaToken 为空。校验通过后返回的 captchaToken 用于登录(1.1)与找回密码(8.4),且为一次性凭证。


Forgot Password 模块

修改密码需通过以下三段式流程完成,该模块全部接口免 Token 校验。流程起点仍需先过滑块验证码。

9.1 发送验证码

POST /api/passport/service/v1/account/forgot-password/send-code

请求体

参数类型必填说明
captchaTokenstring滑块验证码票据(见 8.3)
emailstring注册时使用的邮箱

响应

{
  "code": 0,
  "message": "success"
}

失败时返回 HTTP 200 与对应的业务码(见「错误码」),例如 4001 Email not registered

9.2 校验验证码

POST /api/passport/service/v1/account/forgot-password/verify-code

请求体

参数类型必填说明
emailstring邮箱
codestring邮件中的验证码

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "resetToken": "xxxxxxxx"
  }
}

9.3 重置密码

POST /api/passport/service/v1/account/forgot-password/reset

请求体

参数类型必填说明
emailstring邮箱
resetTokenstring8.5 返回的 resetToken
newPasswordstring新密码

响应

{
  "code": 0,
  "message": "success"
}

完整流程

  1. 调用 8.2 获取滑块验证码素材
  2. 调用 8.3 提交滑块位置,换取 captchaToken
  3. 调用 9.1(携带 captchaToken 与邮箱)发送邮件验证码
  4. 调用 9.2(携带邮箱与邮件验证码)换取 resetToken
  5. 调用 9.3(携带邮箱、resetToken、新密码)完成重置

错误码

通用

错误码HTTP 状态码说明
0200成功
-1500服务端异常或参数绑定失败,message 为具体错误描述
403403越权操作
11002401Token 缺失或无效({"code":11002,"message":"Not authorized"}

登录(Login)

错误码说明
10001Account not found(账号不存在)
10002Incorrect password(密码错误)
10003Account locked due to too many failed attempts(失败次数超限,账号已锁定)
10004Account is disabled(账号已禁用)
10005Captcha verification failed(滑块验证码校验失败)

以上错误码均伴随 HTTP 200 返回,请通过 body 中的 code 判断,不要只看 HTTP 状态码。

找回密码(Forgot Password)

错误码说明
4001Email not registered(邮箱未注册)
4002Invalid verification code(验证码错误)
4003Verification code expired(验证码已过期)
4004Invalid reset token(resetToken 无效)
4005Too many attempts(尝试次数过多)
4006Captcha verification failed(滑块验证码校验失败)
5001Unknown error(兜底错误)

同样伴随 HTTP 200 返回。

管理端(passport-admin)

管理端服务使用独立的错误码空间:

错误码说明
10001Forbidden(无权限)
10002资源 ID 重复
10004参数非法

认证流程

个人账号登录流程

  1. 调用「生成滑块验证码」获取验证码素材
  2. 调用「校验滑块验证码」提交滑块位置,换取 captchaToken
  3. 调用「用户登录」,携带 captchaToken、登录名、密码
  4. 保存返回的 token,后续请求在 passport-token 请求头或 passport_token Cookie 中携带

扫码登录流程

Web 端与扫码设备端的完整接入步骤见「扫码登录接入」的「接入清单」。

App 登录与续期流程

  1. 调用「生成滑块验证码」+「校验滑块验证码」换取 captchaToken
  2. 调用「App 登录」(1.3),安全保存返回的 tokenrefreshToken
  3. access token 过期(或收到 401)时,调用「刷新 Token」(2.5)静默续期;刷新失败则回登录页
  4. 登出时携带 refreshToken 调用 DELETE /login,服务端吊销后清除本地存储

应用账号换取 Token 流程

  1. 调用「生成签名」,传入 accessKeyIdsecretAccessKey,获得 signaturetimestamp
  2. 调用「生成 Token」,传入 accessKeyIdtimestampsignature
  3. 保存返回的 Token 字符串,后续请求在 passport-token 请求头中携带
  4. Token 有效期 24 小时且不支持续期,过期后重新执行本流程(SDK 已内置该流程与缓存,参见「SDK 集成」章节)

权限判断

Token 的 pids 声明中携带了账号被授予的权限 ID 列表。接入方有两种做法:

  1. 直接解析 JWT 的 pids 声明(需持有公钥校验签名)
  2. 调用「同步权限列表」接口获取权限定义,与 pids 比对

注意:Go SDK 当前版本不会解析 pidsAccountInfo.PermissionIds 字段恒为空,需自行解析。