OAuth2.1 认证API配置
你好呀,我的老朋友!我是老寇,欢迎来到老寇IoT云平台!
# 通用说明
# 基础URL
| 环境 | URL |
|---|---|
| 开发环境 | http://gateway:1111/api |
| 测试环境 | https://gateway:1111/api |
| 生产环境 | https://gateway:1111/api |
# 客户端认证
所有认证请求需要在 Authorization 头中携带客户端凭证:
Authorization: Basic {Base64(client_id:client_secret)}
默认客户端凭证:
| 客户端类型 | Client ID | Client Secret | Base64 编码 |
|---|---|---|---|
| 默认客户端 | 95TxSsTPFA3tF12TBSMmUVK0da | FpHwIfw4wY92dO | OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8= |
| PKCE客户端 | eb7Ded5bbFbd7896f8a2cfdDc9 | DpAkPfz4eW18d2 | (无需认证,使用 PKCE) |
# 支持的授权类型
| 授权类型 (grant_type) | 描述 |
|---|---|
username_password | 用户名密码登录 |
mobile | 手机号登录 |
mail | 邮箱登录 |
authorization_code | 授权码登录 |
client_credentials | 客户端凭证登录 |
urn:ietf:params:oauth:grant-type:device_code | 设备码登录 |
refresh_token | 刷新令牌 |
test | 测试登录 |
# 通用响应格式
成功响应:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "3baVWlvnqHKJJtIx5Bjh56soxkFWIeqxGBkfMP64KXir...",
"token_type": "Bearer",
"expires_in": 300,
"scope": "read write"
}
错误响应:
{
"error": "invalid_grant",
"error_description": "用户名或密码错误"
}
# 验证码相关 API
# 获取图形验证码
获取用于用户名密码登录的图形验证码。
| 属性 | 值 |
|---|---|
| URL | /v1/captchas/{uuid} |
| Method | GET |
| 认证 | 无需认证 |
| 限流 | IP 限流 |
路径参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
uuid | string | 是 | 唯一标识符,用于关联验证码 |
请求示例:
GET /api/v1/captchas/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: gateway:1111
成功响应:
{
"code": 0,
"msg": "success",
"data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
# 发送手机验证码
发送手机短信验证码,用于手机号登录。
| 属性 | 值 |
|---|---|
| URL | /v1/captchas/send/mobile |
| Method | POST |
| Content-Type | application/json |
| 认证 | 无需认证 |
| 限流 | IP 限流 + 幂等性校验 |
请求体:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
uuid | string | 是 | 手机号 |
tenantCode | string | 是 | 租户编码 |
请求示例:
POST /api/v1/captchas/send/mobile HTTP/1.1
Host: gateway:1111
Content-Type: application/json
{
"uuid": "18888888888",
"tenantCode": "laokou"
}
成功响应: HTTP 200 (无响应体)
# 发送邮箱验证码
发送邮箱验证码,用于邮箱登录。
| 属性 | 值 |
|---|---|
| URL | /v1/captchas/send/mail |
| Method | POST |
| Content-Type | application/json |
| 认证 | 无需认证 |
| 限流 | IP 限流 + 幂等性校验 |
请求体:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
uuid | string | 是 | 邮箱地址 |
tenantCode | string | 是 | 租户编码 |
请求示例:
POST /api/v1/captchas/send/mail HTTP/1.1
Host: gateway:1111
Content-Type: application/json
{
"uuid": "user@example.com",
"tenantCode": "laokou"
}
成功响应: HTTP 200 (无响应体)
# 密钥 API
# 获取安全密钥
获取用于加密用户名和密码的 RSA 公钥。
| 属性 | 值 |
|---|---|
| URL | /v1/secrets |
| Method | GET |
| 认证 | 无需认证 |
| 限流 | IP 限流 |
请求示例:
GET /api/v1/secrets HTTP/1.1
Host: gateway:1111
成功响应:
{
"code": 0,
"msg": "success",
"data": {
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB..."
}
}
[!IMPORTANT] 用户名和密码需要使用返回的公钥进行 RSA 加密后再提交。
# 认证 API
所有认证请求都使用同一个端点 /oauth2/token,通过 grant_type 参数区分不同的认证方式。
# 1. 用户名密码登录
使用用户名和密码进行认证。
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: username_password |
username | string | 是 | 用户名 (RSA 加密) |
password | string | 是 | 密码 (RSA 加密) |
uuid | string | 是 | 验证码唯一标识 |
captcha | string | 是 | 图形验证码 |
tenant_code | string | 是 | 租户编码 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
username_password
--WebAppBoundary
Content-Disposition: form-data; name="username"
{RSA加密后的用户名}
--WebAppBoundary
Content-Disposition: form-data; name="password"
{RSA加密后的密码}
--WebAppBoundary
Content-Disposition: form-data; name="uuid"
550e8400-e29b-41d4-a716-446655440000
--WebAppBoundary
Content-Disposition: form-data; name="captcha"
HGXZ
--WebAppBoundary
Content-Disposition: form-data; name="tenant_code"
laokou
--WebAppBoundary
cURL 示例:
curl -X POST "https://gateway:1111/api/oauth2/token" \
-H "Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=" \
-F "grant_type=username_password" \
-F "username={RSA加密后的用户名}" \
-F "password={RSA加密后的密码}" \
-F "uuid=550e8400-e29b-41d4-a716-446655440000" \
-F "captcha=HGXZ" \
-F "tenant_code=laokou"
# 2. 手机号登录
使用手机号和短信验证码进行认证。
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: mobile |
mobile | string | 是 | 手机号 |
code | string | 是 | 短信验证码 |
tenant_code | string | 是 | 租户编码 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
mobile
--WebAppBoundary
Content-Disposition: form-data; name="mobile"
18888888888
--WebAppBoundary
Content-Disposition: form-data; name="code"
123456
--WebAppBoundary
Content-Disposition: form-data; name="tenant_code"
laokou
--WebAppBoundary
cURL 示例:
curl -X POST "https://gateway:1111/api/oauth2/token" \
-H "Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=" \
-F "grant_type=mobile" \
-F "mobile=18888888888" \
-F "code=123456" \
-F "tenant_code=laokou"
# 3. 邮箱登录
使用邮箱和邮箱验证码进行认证。
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: mail |
mail | string | 是 | 邮箱地址 |
code | string | 是 | 邮箱验证码 |
tenant_code | string | 是 | 租户编码 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
mail
--WebAppBoundary
Content-Disposition: form-data; name="mail"
user@example.com
--WebAppBoundary
Content-Disposition: form-data; name="code"
654321
--WebAppBoundary
Content-Disposition: form-data; name="tenant_code"
laokou
--WebAppBoundary
cURL 示例:
curl -X POST "https://gateway:1111/api/oauth2/token" \
-H "Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=" \
-F "grant_type=mail" \
-F "mail=user@example.com" \
-F "code=654321" \
-F "tenant_code=laokou"
# 4. 授权码登录
OAuth2.1 标准授权码模式,需要 PKCE 支持。
# 步骤 1: 获取授权码
| 属性 | 值 |
|---|---|
| URL | /oauth2/authorize |
| Method | GET |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
client_id | string | 是 | 客户端 ID |
response_type | string | 是 | 固定值: code |
scope | string | 是 | 权限范围,如 read write |
redirect_uri | string | 是 | 回调地址 |
code_challenge | string | 是 | PKCE 挑战码 |
code_challenge_method | string | 是 | 固定值: S256 |
获取授权码示例 URL:
https://gateway:1111/api/oauth2/authorize?client_id=eb7Ded5bbFbd7896f8a2cfdDc9&response_type=code&scope=read%20write&redirect_uri=http://127.0.0.1:8000&code_challenge=xxxxx&code_challenge_method=S256
用户登录后,浏览器将重定向到:
http://127.0.0.1:8000?code=K7gA8Wm6CKKZPBf-Xhhl-nM5PS_3vi8htN7DEeZrTnq...
# 步骤 2: 使用授权码换取令牌
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: authorization_code |
code | string | 是 | 授权码 |
redirect_uri | string | 是 | 回调地址 (必须与步骤1一致) |
code_verifier | string | 是 | PKCE 验证码 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
authorization_code
--WebAppBoundary
Content-Disposition: form-data; name="code"
K7gA8Wm6CKKZPBf-Xhhl-nM5PS_3vi8htN7DEeZrTnqTHCx0LH7Yx3hHVLBh5x0MkyxVpDGsGabb9OOM6V1-PfI4V6BOlu9q59IK8Bmmvap8Fbgw7rvLCsJoCurG1rz_
--WebAppBoundary
Content-Disposition: form-data; name="redirect_uri"
http://127.0.0.1:8000
--WebAppBoundary
Content-Disposition: form-data; name="code_verifier"
{PKCE_code_verifier}
--WebAppBoundary
# 5. 客户端登录
OAuth2.1 客户端凭证模式,用于服务间认证。
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: client_credentials |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
client_credentials
--WebAppBoundary
cURL 示例:
curl -X POST "https://gateway:1111/api/oauth2/token" \
-H "Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=" \
-F "grant_type=client_credentials"
# 6. 设备码登录
OAuth2.1 设备授权码模式,用于物联网设备等无浏览器场景。
# 步骤 1: 获取设备码
| 属性 | 值 |
|---|---|
| URL | /oauth2/device_authorization |
| Method | POST |
| Content-Type | application/x-www-form-urlencoded |
| Authorization | Basic {credentials} |
请求示例:
POST /api/oauth2/device_authorization HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: application/x-www-form-urlencoded
响应示例:
{
"device_code": "RZ84zoHsQRGxb0mn1AZ0M3QRHfyEB7MBoEniQtd6POS...",
"user_code": "ABCD-EFGH",
"verification_uri": "https://gateway:1111/api/oauth2/device_verification",
"verification_uri_complete": "https://gateway:1111/api/oauth2/device_verification?user_code=ABCD-EFGH",
"expires_in": 300,
"interval": 5
}
# 步骤 2: 用户在浏览器中授权
用户访问 verification_uri 并输入 user_code 完成授权。
# 步骤 3: 设备轮询获取令牌
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: urn:ietf:params:oauth:grant-type:device_code |
device_code | string | 是 | 设备码 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
urn:ietf:params:oauth:grant-type:device_code
--WebAppBoundary
Content-Disposition: form-data; name="device_code"
RZ84zoHsQRGxb0mn1AZ0M3QRHfyEB7MBoEniQtd6POSRFNCvYxzVgydTXvV2Ppi6zaaTnJYreRyPCNzHiaciLVjZdwQz6uV2d8Q_fbxOTM5EqMu9Wht_gH10NKYZzNoe
--WebAppBoundary
# 7. 刷新令牌
使用刷新令牌获取新的访问令牌。
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: refresh_token |
refresh_token | string | 是 | 刷新令牌 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
refresh_token
--WebAppBoundary
Content-Disposition: form-data; name="refresh_token"
3baVWlvnqHKJJtIx5Bjh56soxkFWIeqxGBkfMP64KXir1XV1cXen90oztdR4mpkyHBbnAlqIn3lHtED19pL-YyqtD6tSOez3lTExzaUICCD7GBAAwEmPOst1k7aCQnBZ
--WebAppBoundary
cURL 示例:
curl -X POST "https://gateway:1111/api/oauth2/token" \
-H "Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=" \
-F "grant_type=refresh_token" \
-F "refresh_token={your_refresh_token}"
# 8. 测试登录
用于开发和测试环境的简化登录方式,无需验证码和加密。
| 属性 | 值 |
|---|---|
| URL | /oauth2/token |
| Method | POST |
| Content-Type | multipart/form-data |
| Authorization | Basic {credentials} |
[!CAUTION] 此方式仅用于测试环境,生产环境应禁用。
请求参数:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
grant_type | string | 是 | 固定值: test |
username | string | 是 | 用户名 (明文) |
password | string | 是 | 密码 (明文) |
tenant_code | string | 是 | 租户编码 |
请求示例:
POST /api/oauth2/token HTTP/1.1
Host: gateway:1111
Authorization: Basic OTVUeFNzVFBGQTN0RjEyVEJTTW1VVkswZGE6RnBId0lmdzR3WTkyZE8=
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="grant_type"
test
--WebAppBoundary
Content-Disposition: form-data; name="username"
admin
--WebAppBoundary
Content-Disposition: form-data; name="password"
admin123
--WebAppBoundary
Content-Disposition: form-data; name="tenant_code"
laokou
--WebAppBoundary
# 令牌管理 API
# 删除令牌
注销用户会话,删除令牌。
| 属性 | 值 |
|---|---|
| URL | /v1/tokens |
| Method | DELETE |
| Content-Type | application/json |
| 认证 | 无需认证 |
请求体:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
token | string | 是 | 要删除的访问令牌 |
请求示例:
DELETE /api/v1/tokens HTTP/1.1
Host: gateway:1111
Content-Type: application/json
{
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
# 错误码说明
| 错误码 | 描述 |
|---|---|
B_OAuth2_DeptNotFound | 部门不存在 |
B_OAuth2_TenantNotFound | 租户不存在 |
B_OAuth2_GenerateRefreshTokenFail | 刷新令牌生成失败 |
B_OAuth2_GenerateAccessTokenFail | 访问令牌生成失败 |
B_OAuth2_RegisteredClientNotFound | 注册客户端不存在 |
B_OAuth2_InvalidClient | 无效客户端 |
B_OAuth2_InvalidScope | 无效作用域 |
B_OAuth2_UserDisabled | 用户已禁用 |
B_OAuth2_CaptchaExpired | 验证码已过期 |
B_OAuth2_CaptchaError | 验证码错误 |
B_OAuth2_UsernamePasswordError | 用户名或密码错误 |
B_OAuth2_MobileNotRegistered | 手机号未注册 |
B_OAuth2_MailNotRegistered | 邮箱未注册 |
P_OAuth2_UuidIsNull | UUID 不能为空 |
P_OAuth2_CaptchaIsNull | 验证码不能为空 |
P_OAuth2_UsernameIsNull | 用户名不能为空 |
P_OAuth2_PasswordIsNull | 密码不能为空 |
P_OAuth2_MobileIsNull | 手机号不能为空 |
P_OAuth2_MailIsNull | 邮箱不能为空 |
P_OAuth2_TenantCodeIsNull | 租户编码不能为空 |
P_OAuth2_MailError | 邮箱格式错误 |
P_OAuth2_MobileError | 手机号格式错误 |
# 令牌有效期
| 令牌类型 | 默认有效期 |
|---|---|
| 授权码 | 5 分钟 |
| 访问令牌 | 5 分钟 |
| 刷新令牌 | 1 小时 |
| 设备码 | 5 分钟 |
我是老寇,我们下次再见啦!