Files
SecScore/AUTH/AUTH.MD
T
Yukino_fox 7a59572f11 feat(auth): 添加 SECTL Auth OAuth 登录功能
- 新增 OAuth 登录组件和回调页面
- 集成 Tauri 深度链接插件处理 OAuth 回调
- 添加账户设置页面显示登录信息
- 更新 CI 配置添加 OAuth 环境变量
- 扩展 API 接口支持 OAuth 相关操作
- 添加国际化支持
2026-03-29 19:30:27 +08:00

12 KiB
Raw Blame History

平台接入指南

本文档介绍如何将第三方平台与 SECTL Auth 集成,实现统一认证和远程退登功能。

目录

概述

SECTL Auth 提供以下核心功能:

  1. 统一认证 - 用户使用 SECTL Auth 账号登录第三方平台
  2. 远程退登 - 用户在 SECTL Auth 中心退出后,平台自动退出
  3. 用户管理 - 查看已授权用户、统计信息等

工作流程

┌─────────────┐     登录请求    ┌─────────────┐
│   用户      │ ─────────────> │  SECTL Auth │
│             │                │             │
│   平台A     │ <───────────── │   认证中心   │
│             │   Access Token │             │
└──────┬──────┘                └──────┬──────┘
       │                              │
       │      远程退登通知             │
       │ <─────────────────────────── │
       │      (Realtime)              │
       ▼                              ▼
  自动退出登录                   用户点击退出

快速开始

1. 注册平台

在 SECTL Auth 平台管理页面 (PlatformManagementView.vue) 申请接入,获取:

参数 说明 示例
platform_id 平台唯一标识 pf_AHmIhAiptyLFxk8x
platform_token 平台认证密钥 sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1
callback_url 回调地址 http://localhost:5000/callback

2. 平台状态说明

平台在管理后台有以下状态:

状态 说明 可操作
active 运行中 正常授权
pending 审核中 等待审核
disabled 已停用 无法授权

3. 查看统计信息

在平台管理页面可以查看:

  • 总平台数 - 已创建的平台数量
  • 运行中 - 活跃平台数量
  • 审核中 - 待审核申请数量
  • 总用户数 - 授权用户总数

管理后台功能

平台列表 (PlatformManagementView.vue)

平台管理页面提供以下功能:

1. 平台卡片展示

每个平台显示:

  • 平台名称和描述
  • 状态标签(运行中/审核中/已停用)
  • 创建时间
  • 授权用户数
  • 管理按钮

2. 搜索和过滤

  • 按名称搜索平台
  • 按状态过滤
  • 分页展示

3. 快捷操作

  • 新建平台 - 跳转到申请页面
  • 我的申请 - 查看自己的平台申请
  • 审核申请 - 审核其他用户的申请(需 >=18 权限)

平台详情 (PlatformDetailView.vue)

查看平台详细信息:

基本信息

  • 平台 ID (Client ID)
  • 平台密钥 (Client Secret)
  • 回调地址
  • 创建时间

安全设置

  • Token 过期时间配置
  • 密钥重置
  • 回调地址修改

用户统计

  • 授权用户列表
  • 登录时间
  • 最后活跃时间

平台申请 (PlatformApplyView.vue)

申请创建新平台:

// 申请参数
{
  name: "我的应用",           // 平台名称
  description: "应用描述",   // 平台描述
  callback_url: "http://..." // 回调地址
}

申请后状态为 pending,等待管理员审核。

申请审核 (PlatformApplicationsView.vue)

管理员审核平台申请:

  • 查看申请详情
  • 批准申请(状态变为 active
  • 拒绝申请(状态变为 disabled

OAuth 集成

授权流程

1. 引导用户到授权页面

GET https://sectl.top/oauth/authorize

参数:

参数名 必填 说明
client_id 平台 ID
redirect_uri 回调地址
response_type 固定值 code

示例:

https://sectl.top/oauth/authorize?client_id=pf_xxx&redirect_uri=http://localhost:5000/callback&response_type=code

2. 处理回调

用户授权后,会重定向到:

{callback_url}?code={authorization_code}

3. 换取访问令牌

POST https://sectl.top/api/oauth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "授权码",
  "client_id": "pf_xxx",
  "client_secret": "sk_xxx",
  "redirect_uri": "http://localhost:5000/callback"
}

响应:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "xxx",
  "token_type": "Bearer",
  "expires_in": 3600
}

4. 获取用户信息

GET https://sectl.top/api/oauth/userinfo
Authorization: Bearer {access_token}

响应:

{
  "user_id": "69bd422960018cf4d0e5",
  "email": "user@example.com",
  "name": "张三",
  "github_username": "zhangsan"
}

远程退登

实现原理

  1. 用户在 SECTL Auth 点击退出登录
  2. 系统创建 logout_events 文档
  3. 第三方应用通过 Appwrite Realtime 订阅该集合
  4. 收到匹配的事件后执行本地退出

集成步骤

1. 安装 Appwrite SDK

C#

dotnet add package Appwrite

Python

pip install appwrite

2. 配置 Realtime 订阅

C# 示例:

using Appwrite;
using Appwrite.Services;

var client = new Client()
    .SetEndpoint("https://cloud.appwrite.io/v1")
    .SetProject("your-project-id");

var realtime = new Realtime(client);

// 订阅 logout_events 集合
realtime.Subscribe("databases.{databaseId}.collections.logout_events.documents",
    callback: (message) => {
        var logoutEvent = message.Payload;
        if (logoutEvent.UserId == currentUserId) {
            // 执行本地退出
            LocalLogout();
        }
    });

Python 示例:

from appwrite.client import Client
from appwrite.services.realtime import Realtime

client = Client()
client.set_endpoint('https://cloud.appwrite.io/v1')
client.set_project('your-project-id')

realtime = Realtime(client)

def on_logout_event(message):
    event = message['payload']
    if event['user_id'] == current_user_id:
        # 执行本地退出
        local_logout()

# 订阅 logout_events 集合
realtime.subscribe(
    'databases.{database_id}.collections.logout_events.documents',
    callback=on_logout_event
)

数据结构

logout_events 集合字段:

字段 类型 说明
user_id String 退出登录的用户ID
platform_id String 特定平台ID(可选)
global Boolean 是否全局退出
created_at String 创建时间

代码示例

C# 完整示例

详见 csharp-example 目录。

// SectlAuthClient.cs
public class SectlAuthClient
{
    private readonly string _platformId;
    private readonly string _platformSecret;
    private readonly string _callbackUrl;
    private readonly HttpClient _httpClient;

    public SectlAuthClient(string platformId, string platformSecret, string callbackUrl)
    {
        _platformId = platformId;
        _platformSecret = platformSecret;
        _callbackUrl = callbackUrl;
        _httpClient = new HttpClient();
    }

    // 获取授权 URL
    public string GetAuthorizationUrl()
    {
        return $"https://sectl.top/oauth/authorize?" +
               $"client_id={_platformId}&" +
               $"redirect_uri={Uri.EscapeDataString(_callbackUrl)}&" +
               $"response_type=code";
    }

    // 换取访问令牌
    public async Task<TokenResponse> ExchangeCodeAsync(string code)
    {
        var request = new
        {
            grant_type = "authorization_code",
            code = code,
            client_id = _platformId,
            client_secret = _platformSecret,
            redirect_uri = _callbackUrl
        };

        var response = await _httpClient.PostAsJsonAsync(
            "https://sectl.top/api/oauth/token", request);

        return await response.Content.ReadFromJsonAsync<TokenResponse>();
    }

    // 获取用户信息
    public async Task<UserInfo> GetUserInfoAsync(string accessToken)
    {
        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", accessToken);

        var response = await _httpClient.GetAsync(
            "https://sectl.top/api/oauth/userinfo");

        return await response.Content.ReadFromJsonAsync<UserInfo>();
    }
}

Python 完整示例

详见 python-example 目录。

# sectl_auth/client.py
import requests

class SectlAuthClient:
    BASE_URL = "https://sectl.top"
    AUTH_URL = "https://sectl.top"

    def __init__(self, platform_id: str, platform_secret: str, callback_url: str):
        self.platform_id = platform_id
        self.platform_secret = platform_secret
        self.callback_url = callback_url

    def get_authorization_url(self) -> str:
        """获取授权 URL"""
        return (
            f"{self.AUTH_URL}/oauth/authorize?"
            f"client_id={self.platform_id}&"
            f"redirect_uri={self.callback_url}&"
            f"response_type=code"
        )

    def exchange_code(self, code: str) -> dict:
        """用授权码换取访问令牌"""
        response = requests.post(
            f"{self.BASE_URL}/api/oauth/token",
            json={
                "grant_type": "authorization_code",
                "code": code,
                "client_id": self.platform_id,
                "client_secret": self.platform_secret,
                "redirect_uri": self.callback_url
            }
        )
        response.raise_for_status()
        return response.json()

    def get_user_info(self, access_token: str) -> dict:
        """获取用户信息"""
        response = requests.get(
            f"{self.BASE_URL}/api/oauth/userinfo",
            headers={"Authorization": f"Bearer {access_token}"}
        )
        response.raise_for_status()
        return response.json()

常见问题

Q: 如何获取 platform_id 和 platform_token

A: 在 SECTL Auth 平台管理页面申请创建平台,审核通过后会获得:

  • platform_id (Client ID)
  • platform_token (Client Secret)

Q: 授权码有效期多久?

A: 授权码有效期为 10 分钟,且只能使用一次。

Q: Access Token 过期后怎么办?

A: 使用 refresh_token 换取新的 access_token

POST /api/oauth/token
{
  "grant_type": "refresh_token",
  "refresh_token": "your-refresh-token",
  "client_id": "your-platform-id",
  "client_secret": "your-platform-secret"
}

Q: 如何配置 Token 过期时间?

A: 在平台设置页面 (PlatformSettingsView.vue) 可以配置:

  • access_token 过期时间(默认 3600 秒)
  • 设置为 -1 表示永不过期

Q: 远程退登不生效怎么办?

A: 检查以下几点:

  1. 是否正确订阅了 logout_events 集合
  2. 检查 user_id 是否匹配
  3. 确认 Appwrite Realtime 连接正常
  4. 查看浏览器控制台是否有错误

Q: 平台状态显示"审核中"怎么办?

A: 新创建的平台需要管理员审核。审核通过后状态会变为 active

相关页面

参考文档