# 平台账号管理接口文档 **版本**: V1.0 **日期**: 2026-01-XX **状态**: 已发布 本文档详细描述了统一认证平台(UAP)的平台账号管理相关接口,包括查询用户账号映射列表和 SSO 单点登录功能。 --- ## 1. 概述 平台账号管理接口允许用户查询和管理自己在各个第三方应用中的账号映射关系,并支持通过 SSO 方式快速登录到目标应用。 ### 1.1 核心概念 - **账号映射 (User Mapping)**: 统一认证平台用户与第三方应用账号的关联关系 - **映射账号 (Mapped Key)**: 用户在第三方系统中的唯一标识 - **映射邮箱 (Mapped Email)**: 用户在第三方系统中的邮箱地址 - **SSO 登录**: 单点登录,用户无需再次输入密码即可进入第三方应用 ### 1.2 接口权限说明 | 接口 | 认证方式 | 说明 | |------|---------|------| | `GET /simple/me/mappings` | Bearer Token (用户认证) | 仅用户可查询自己的账号映射 | | `POST /simple/sso-login` | Bearer Token (可选) 或 用户名密码 | 支持会话认证和凭据认证两种模式 | --- ## 2. 认证方式 ### 2.1 用户认证 (Bearer Token) 适用于前端应用或已登录的用户。 **请求头格式:** ``` Authorization: Bearer {access_token} ``` **获取 Token:** - 通过 `POST /auth/login/json` 接口登录获取 - 或通过 `POST /simple/login` 接口(不提供 app_id)获取平台 access_token ### 2.2 凭据认证 (用户名密码) 适用于用户未登录 UAP 平台的场景,直接使用用户名和密码进行认证。 --- ## 3. 接口定义 ### 3.1 获取我的账号映射列表 查询当前用户在所有第三方应用中的账号映射关系。 - **接口地址**: `GET {{API_BASE_URL}}/simple/me/mappings` - **认证方式**: Bearer Token (用户认证) - **Content-Type**: `application/json` #### 3.1.1 请求参数 (Query Parameters) | 字段 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `skip` | integer | 否 | 0 | 跳过的记录数(用于分页) | | `limit` | integer | 否 | 10 | 每页返回的记录数 | | `app_name` | string | 否 | - | 应用名称(支持模糊搜索) | #### 3.1.2 响应格式 **成功响应 (200 OK):** ```json { "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: 已禁用) | #### 3.1.3 错误响应 **401 Unauthorized - 未认证:** ```json { "detail": "Not authenticated" } ``` **403 Forbidden - 无权限:** ```json { "detail": "Not enough permissions" } ``` #### 3.1.4 请求示例 **cURL:** ```bash curl -X GET "{{API_BASE_URL}}/simple/me/mappings?skip=0&limit=10&app_name=OA" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` **JavaScript (Fetch API):** ```javascript 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):** ```python 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']}") ``` --- ### 3.2 SSO 单点登录 通过 SSO 方式登录到目标应用,支持两种认证模式: 1. **会话认证模式**: 用户已登录 UAP 平台,使用 Bearer Token 2. **凭据认证模式**: 用户未登录,使用用户名和密码 - **接口地址**: `POST {{API_BASE_URL}}/simple/sso-login` - **认证方式**: - Bearer Token (会话认证,推荐) - 或 用户名密码 (凭据认证) - **Content-Type**: `application/json` - **限制**: 仅支持 `SIMPLE_API` 协议类型的应用 #### 3.2.1 请求参数 (Request Body) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `app_id` | string | 是 | 目标应用的ID | | `username` | string | 条件必填 | 用户名(手机号、映射key或映射email)。如果已登录UAP平台,可不提供 | | `password` | string | 条件必填 | 用户密码。如果已登录UAP平台,可不提供 | **注意:** - 如果用户已登录 UAP 平台(请求头包含有效的 Bearer Token),则 `username` 和 `password` 可以省略 - 如果用户未登录,则必须提供 `username` 和 `password` #### 3.2.2 响应格式 **成功响应 (200 OK):** ```json { "redirect_url": "https://oa.company.com/login?ticket=TICKET-7f8e9d0a-1234-5678-9abc-def012345678" } ``` **响应字段说明:** | 字段 | 类型 | 说明 | |------|------|------| | `redirect_url` | string | 包含 SSO Ticket 的完整跳转URL,客户端应在新窗口/标签页中打开 | #### 3.2.3 错误响应 **400 Bad Request - 应用未找到或协议不支持:** ```json { "detail": "应用未找到" } ``` 或 ```json { "detail": "SSO 登录仅支持简易 API 应用。OIDC 请使用标准流程。" } ``` **401 Unauthorized - 认证失败:** ```json { "detail": "认证失败" } ``` **400 Bad Request - 用户已禁用:** ```json { "detail": "用户已禁用" } ``` **400 Bad Request - 应用未配置重定向URI:** ```json { "detail": "应用未配置重定向 URI" } ``` #### 3.2.4 请求示例 **场景1: 用户已登录 UAP 平台(会话认证)** **cURL:** ```bash 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):** ```javascript // 用户已登录,使用 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:** ```bash 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):** ```javascript // 用户未登录,使用用户名密码 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):** ```python 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']}") ``` --- ## 4. 完整集成示例 ### 4.1 前端 Vue.js 示例 ```vue ``` ### 4.2 后端 Python 示例 ```python 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}") ``` --- ## 5. 注意事项 ### 5.1 协议类型限制 - `GET /simple/me/mappings` 接口返回所有类型的应用映射 - `POST /simple/sso-login` 接口**仅支持 `SIMPLE_API` 协议类型**的应用 - 对于 `OIDC` 协议类型的应用,请使用标准的 OIDC 流程进行登录 ### 5.2 账号状态 - 只有 `is_active: true` 的账号映射才能进行 SSO 登录 - 如果账号被禁用,SSO 登录会返回错误 ### 5.3 安全建议 1. **Token 安全**: Bearer Token 应妥善保管,避免泄露 2. **HTTPS**: 生产环境必须使用 HTTPS 协议 3. **Token 过期**: 注意处理 Token 过期的情况,及时刷新或重新登录 4. **错误处理**: 建议实现完善的错误处理和重试机制 ### 5.4 分页建议 - 默认每页返回 10 条记录 - 建议根据实际需求设置合适的 `limit` 值(最大建议 100) - 使用 `skip` 和 `limit` 实现分页导航 --- ## 6. 常见问题 (FAQ) ### Q1: 为什么 SSO 登录返回 400 错误,提示"协议不支持"? **A:** `POST /simple/sso-login` 接口仅支持 `SIMPLE_API` 协议类型的应用。如果您的应用是 `OIDC` 类型,请使用标准的 OIDC 认证流程。 ### Q2: 如何判断用户是否已登录 UAP 平台? **A:** 如果您的应用中有有效的 `access_token`,可以在请求头中携带 `Authorization: Bearer {token}`。如果 Token 有效,则无需提供 `username` 和 `password`。 ### Q3: 账号映射列表中的 `mapped_email` 为什么可能为空? **A:** 不是所有第三方应用都要求或提供邮箱信息,因此 `mapped_email` 字段可能为 `null`。这是正常情况。 ### Q4: 如何实现"记住我"功能? **A:** 建议在客户端(浏览器)安全地存储 `access_token`(如使用 httpOnly Cookie 或安全的 localStorage),并在每次请求时携带该 Token。 ### Q5: SSO 登录后,Ticket 的有效期是多久? **A:** Ticket 的有效期由平台配置决定,通常为 5-10 分钟。建议在获取 `redirect_url` 后立即跳转,避免 Ticket 过期。 --- ## 7. 更新日志 | 版本 | 日期 | 更新内容 | |------|------|---------| | V1.0 | 2026-01-XX | 初始版本发布 | --- ## 8. 技术支持 如有问题或建议,请联系技术支持团队或查看项目文档。 **文档地址**: `{{DOCS_BASE_URL}}/docs/account_management_api.md`