# 统一认证平台 - 简易认证 (Simple Auth) 集成指南

## 1. 概述
本指南适用于需要使用自定义登录页面（而非跳转到认证中心标准页面），并通过后端 API 直接进行用户认证的场景。

**Base URL**: `http://localhost:8000/api/v1/simple` (开发环境)

## 2. 核心流程
1. **用户输入**: 用户在客户端输入账号密码。
2. **签名**: 客户端/后端生成签名 (Sign)。
3. **登录**: POST `/login` (账号+密码+签名) -> 获取 `Ticket`。
4. **验证**: POST `/validate` (Ticket+签名) -> 获取用户信息。

## 3. 安全警告
- **App Secret** 严禁泄露给前端浏览器。
- 建议所有涉及 Secret 的签名计算都在**后端**完成。

## 4. 签名算法 (Signature)
所有接口（除部分公开接口外）都需要校验签名。

**步骤**:
1. **准备参数**: 收集所有请求参数（**排除 `sign` 本身**）。
2. **排序**: 按照参数名（key）的 ASCII 码从小到大排序。
3. **拼接**: 将排序后的参数拼接成 `key1=value1&key2=value2...` 格式。
4. **计算 HMAC**: 使用 `App Secret` 作为密钥，对拼接字符串进行 **HMAC-SHA256** 计算。
5. **Hex 编码**: 将结果转换为十六进制字符串。

### Python 示例
```python
import hmac
import hashlib

def generate_signature(secret: str, params: dict) -> str:
    data = {k: v for k, v in params.items() if k != "sign" and v is not None}
    sorted_keys = sorted(data.keys())
    query_string = "&".join([f"{k}={data[k]}" for k in sorted_keys])
    signature = hmac.new(
        secret.encode('utf-8'),
        query_string.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    return signature
```

## 5. 接口定义

### 5.1 密码登录 (Login)
获取临时票据 (Ticket)。

- **URL**: `POST /login`
- **Content-Type**: `application/json`

**Request Body**:
| Field | Type | Required | Description |
|---|---|---|---|
| `app_id` | string | Yes | 应用 ID |
| `identifier` | string | Yes | 用户标识（手机号、用户名或邮箱） |
| `password` | string | Yes | 明文密码 |
| `timestamp` | int | Yes | 当前时间戳 (秒) |
| `sign` | string | Yes | 签名 |

**Response (200)**:
```json
{
  "ticket": "TICKET-7f8e9d0a-..." 
}
```

### 5.2 验证票据 (Validate)
解析票据获取用户信息。

- **URL**: `POST /validate`
- **Content-Type**: `application/json`

**Request Body**:
| Field | Type | Required | Description |
|---|---|---|---|
| `app_id` | string | Yes | 应用 ID |
| `ticket` | string | Yes | 上一步获取的票据 |
| `timestamp` | int | Yes | 当前时间戳 |
| `sign` | string | Yes | 签名 (参数变化需重新计算) |

**Response (200)**:
```json
{
  "valid": true,
  "user_id": 1001,
  "mobile": "13800138000",
  "mapped_key": "user_zhangsan",  // 第三方映射ID
  "mapped_email": "zhangsan@example.com"
}
```

**Response (Invalid)**:
```json
{ "valid": false }
```

