版本: V1.0
日期: 2026-01-XX
状态: 已发布
本文档详细描述了统一认证平台(UAP)的平台账号管理相关接口,包括查询用户账号映射列表和 SSO 单点登录功能。
平台账号管理接口允许用户查询和管理自己在各个第三方应用中的账号映射关系,并支持通过 SSO 方式快速登录到目标应用。
| 接口 | 认证方式 | 说明 |
|---|---|---|
GET /simple/me/mappings |
Bearer Token (用户认证) | 仅用户可查询自己的账号映射 |
POST /simple/sso-login |
Bearer Token (可选) 或 用户名密码 | 支持会话认证和凭据认证两种模式 |
适用于前端应用或已登录的用户。
请求头格式:
Authorization: Bearer {access_token}
获取 Token:
POST /auth/login/json 接口登录获取POST /simple/login 接口(不提供 app_id)获取平台 access_token适用于用户未登录 UAP 平台的场景,直接使用用户名和密码进行认证。
查询当前用户在所有第三方应用中的账号映射关系。
GET {{API_BASE_URL}}/simple/me/mappingsapplication/json| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
skip |
integer | 否 | 0 | 跳过的记录数(用于分页) |
limit |
integer | 否 | 10 | 每页返回的记录数 |
app_name |
string | 否 | - | 应用名称(支持模糊搜索) |
成功响应 (200 OK):
{
"total": 25,
"items": [
{
"app_name": "OA办公系统",
"app_id": "oa_system_001",
"protocol_type": "SIMPLE_API",
"mapped_key": "zhangsan_oa",
"mapped_email": "zhangsan@company.com",
"is_active": true
},
{
"app_name": "CRM客户管理",
"app_id": "crm_system_001",
"protocol_type": "SIMPLE_API",
"mapped_key": "zhangsan_crm",
"mapped_email": null,
"is_active": true
}
]
}
响应字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
total |
integer | 总记录数 |
items |
array | 映射列表 |
items[].app_name |
string | 应用名称 |
items[].app_id |
string | 应用ID |
items[].protocol_type |
string | 协议类型:SIMPLE_API 或 OIDC |
items[].mapped_key |
string | 映射账号(第三方系统账号) |
items[].mapped_email |
string|null | 映射邮箱(可能为空) |
items[].is_active |
boolean | 是否激活(true: 正常, false: 已禁用) |
401 Unauthorized - 未认证:
{
"detail": "Not authenticated"
}
403 Forbidden - 无权限:
{
"detail": "Not enough permissions"
}
cURL:
curl -X GET "{{API_BASE_URL}}/simple/me/mappings?skip=0&limit=10&app_name=OA" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
JavaScript (Fetch API):
const response = await fetch('{{API_BASE_URL}}/simple/me/mappings?skip=0&limit=10&app_name=OA', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log('总记录数:', data.total);
console.log('映射列表:', data.items);
Python (requests):
import requests
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
params = {
'skip': 0,
'limit': 10,
'app_name': 'OA' # 可选,模糊搜索
}
response = requests.get(
'{{API_BASE_URL}}/simple/me/mappings',
headers=headers,
params=params
)
data = response.json()
print(f"总记录数: {data['total']}")
for mapping in data['items']:
print(f"应用: {mapping['app_name']}, 映射账号: {mapping['mapped_key']}")
通过 SSO 方式登录到目标应用,支持两种认证模式:
POST {{API_BASE_URL}}/simple/sso-loginapplication/jsonSIMPLE_API 协议类型的应用| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_id |
string | 是 | 目标应用的ID |
username |
string | 条件必填 | 用户名(手机号、映射key或映射email)。如果已登录UAP平台,可不提供 |
password |
string | 条件必填 | 用户密码。如果已登录UAP平台,可不提供 |
注意:
username 和 password 可以省略username 和 password成功响应 (200 OK):
{
"redirect_url": "https://oa.company.com/login?ticket=TICKET-7f8e9d0a-1234-5678-9abc-def012345678"
}
响应字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
redirect_url |
string | 包含 SSO Ticket 的完整跳转URL,客户端应在新窗口/标签页中打开 |
400 Bad Request - 应用未找到或协议不支持:
{
"detail": "应用未找到"
}
或
{
"detail": "SSO 登录仅支持简易 API 应用。OIDC 请使用标准流程。"
}
401 Unauthorized - 认证失败:
{
"detail": "认证失败"
}
400 Bad Request - 用户已禁用:
{
"detail": "用户已禁用"
}
400 Bad Request - 应用未配置重定向URI:
{
"detail": "应用未配置重定向 URI"
}
场景1: 用户已登录 UAP 平台(会话认证)
cURL:
curl -X POST "{{API_BASE_URL}}/simple/sso-login" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"app_id": "oa_system_001"
}'
JavaScript (Fetch API):
// 用户已登录,使用 Bearer Token
const response = await fetch('{{API_BASE_URL}}/simple/sso-login', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
app_id: 'oa_system_001'
})
});
const data = await response.json();
if (data.redirect_url) {
// 在新标签页中打开
window.open(data.redirect_url, '_blank');
}
场景2: 用户未登录(凭据认证)
cURL:
curl -X POST "{{API_BASE_URL}}/simple/sso-login" \
-H "Content-Type: application/json" \
-d '{
"app_id": "oa_system_001",
"username": "13800138000",
"password": "user_password_123"
}'
JavaScript (Fetch API):
// 用户未登录,使用用户名密码
const response = await fetch('{{API_BASE_URL}}/simple/sso-login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
app_id: 'oa_system_001',
username: '13800138000',
password: 'user_password_123'
})
});
const data = await response.json();
if (data.redirect_url) {
window.open(data.redirect_url, '_blank');
}
Python (requests):
import requests
# 场景1: 会话认证(已登录)
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
data = {
'app_id': 'oa_system_001'
}
response = requests.post(
'{{API_BASE_URL}}/simple/sso-login',
headers=headers,
json=data
)
result = response.json()
print(f"跳转URL: {result['redirect_url']}")
# 场景2: 凭据认证(未登录)
data = {
'app_id': 'oa_system_001',
'username': '13800138000',
'password': 'user_password_123'
}
response = requests.post(
'{{API_BASE_URL}}/simple/sso-login',
headers={'Content-Type': 'application/json'},
json=data
)
result = response.json()
print(f"跳转URL: {result['redirect_url']}")
<template>
<div class="mappings-container">
<el-table :data="mappings" v-loading="loading">
<el-table-column prop="app_name" label="应用名称" />
<el-table-column prop="mapped_key" label="映射账号" />
<el-table-column prop="is_active" label="状态">
<template #default="scope">
<el-tag :type="scope.row.is_active ? 'success' : 'danger'">
{{ scope.row.is_active ? '正常' : '已禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button
type="primary"
size="small"
:disabled="!scope.row.is_active || scope.row.protocol_type !== 'SIMPLE_API'"
:loading="loginLoading[scope.row.app_id]"
@click="handleSsoLogin(scope.row)"
>
进入
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import api from '../utils/request'
interface Mapping {
app_name: string
app_id: string
protocol_type: string
mapped_key: string
mapped_email: string | null
is_active: boolean
}
const mappings = ref<Mapping[]>([])
const loading = ref(false)
const loginLoading = reactive<Record<string, boolean>>({})
// 获取账号映射列表
const fetchMappings = async () => {
loading.value = true
try {
const res = await api.get('/simple/me/mappings', {
params: { skip: 0, limit: 100 }
})
if (res.data) {
mappings.value = res.data.items
}
} catch (error: any) {
ElMessage.error(error.response?.data?.detail || '获取列表失败')
} finally {
loading.value = false
}
}
// SSO 登录
const handleSsoLogin = async (mapping: Mapping) => {
if (!mapping.is_active) {
ElMessage.warning('该账号已禁用,无法登录')
return
}
if (mapping.protocol_type !== 'SIMPLE_API') {
ElMessage.warning('仅支持简易 API 类型的应用')
return
}
loginLoading[mapping.app_id] = true
try {
// 使用会话认证(用户已登录 UAP 平台)
const res = await api.post('/simple/sso-login', {
app_id: mapping.app_id
}, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
})
if (res.data && res.data.redirect_url) {
// 在新标签页中打开目标应用
window.open(res.data.redirect_url, '_blank')
ElMessage.success('正在新标签页中打开应用...')
} else {
ElMessage.error('SSO 登录失败:未返回跳转地址')
}
} catch (error: any) {
console.error('SSO 登录失败:', error)
ElMessage.error(error.response?.data?.detail || 'SSO 登录失败')
} finally {
loginLoading[mapping.app_id] = false
}
}
onMounted(() => {
fetchMappings()
})
</script>
import requests
from typing import List, Dict, Optional
class UAPAccountManager:
"""统一认证平台账号管理客户端"""
def __init__(self, base_url: str, access_token: str):
self.base_url = base_url.rstrip('/')
self.access_token = access_token
self.headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
def get_my_mappings(
self,
skip: int = 0,
limit: int = 10,
app_name: Optional[str] = None
) -> Dict:
"""
获取我的账号映射列表
Args:
skip: 跳过的记录数
limit: 每页返回的记录数
app_name: 应用名称(模糊搜索)
Returns:
{
'total': 总记录数,
'items': [映射列表]
}
"""
params = {'skip': skip, 'limit': limit}
if app_name:
params['app_name'] = app_name
response = requests.get(
f'{self.base_url}/simple/me/mappings',
headers=self.headers,
params=params
)
response.raise_for_status()
return response.json()
def sso_login(
self,
app_id: str,
username: Optional[str] = None,
password: Optional[str] = None
) -> str:
"""
SSO 单点登录
Args:
app_id: 目标应用ID
username: 用户名(可选,如果已登录UAP可不提供)
password: 密码(可选,如果已登录UAP可不提供)
Returns:
跳转URL
"""
data = {'app_id': app_id}
if username and password:
data['username'] = username
data['password'] = password
# 如果提供了用户名密码,不使用 Bearer Token
headers = self.headers if not username else {'Content-Type': 'application/json'}
response = requests.post(
f'{self.base_url}/simple/sso-login',
headers=headers,
json=data
)
response.raise_for_status()
result = response.json()
return result['redirect_url']
# 使用示例
if __name__ == '__main__':
# 初始化客户端
manager = UAPAccountManager(
base_url='{{API_BASE_URL}}',
access_token='your_access_token_here'
)
# 获取账号映射列表
result = manager.get_my_mappings(skip=0, limit=10, app_name='OA')
print(f"总记录数: {result['total']}")
for mapping in result['items']:
print(f"应用: {mapping['app_name']}, 映射账号: {mapping['mapped_key']}")
# SSO 登录(会话认证)
redirect_url = manager.sso_login(app_id='oa_system_001')
print(f"跳转URL: {redirect_url}")
# SSO 登录(凭据认证)
redirect_url = manager.sso_login(
app_id='oa_system_001',
username='13800138000',
password='user_password_123'
)
print(f"跳转URL: {redirect_url}")
GET /simple/me/mappings 接口返回所有类型的应用映射POST /simple/sso-login 接口仅支持 SIMPLE_API 协议类型的应用OIDC 协议类型的应用,请使用标准的 OIDC 流程进行登录is_active: true 的账号映射才能进行 SSO 登录limit 值(最大建议 100)skip 和 limit 实现分页导航A: POST /simple/sso-login 接口仅支持 SIMPLE_API 协议类型的应用。如果您的应用是 OIDC 类型,请使用标准的 OIDC 认证流程。
A: 如果您的应用中有有效的 access_token,可以在请求头中携带 Authorization: Bearer {token}。如果 Token 有效,则无需提供 username 和 password。
mapped_email 为什么可能为空?A: 不是所有第三方应用都要求或提供邮箱信息,因此 mapped_email 字段可能为 null。这是正常情况。
A: 建议在客户端(浏览器)安全地存储 access_token(如使用 httpOnly Cookie 或安全的 localStorage),并在每次请求时携带该 Token。
A: Ticket 的有效期由平台配置决定,通常为 5-10 分钟。建议在获取 redirect_url 后立即跳转,避免 Ticket 过期。
| 版本 | 日期 | 更新内容 |
|---|---|---|
| V1.0 | 2026-01-XX | 初始版本发布 |
如有问题或建议,请联系技术支持团队或查看项目文档。
文档地址: {{DOCS_BASE_URL}}/docs/account_management_api.md