464 lines
19 KiB
Markdown
464 lines
19 KiB
Markdown
# 认证服务
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [routes.go](file://internal/handler/routes.go)
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go)
|
||
- [yggdrasil_service_test.go](file://internal/service/yggdrasil_service_test.go)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go)
|
||
- [jwt.go](file://pkg/auth/jwt.go)
|
||
- [redis.go](file://pkg/redis/redis.go)
|
||
- [response.go](file://internal/model/response.go)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖关系分析](#依赖关系分析)
|
||
7. [性能考量](#性能考量)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本文件面向Yggdrasil认证服务的API文档,聚焦/authserver路由下的以下端点:
|
||
- POST /authenticate:用户凭据认证,返回访问令牌与可用角色信息
|
||
- POST /validate:校验访问令牌有效性
|
||
- POST /refresh:在令牌过期或需要更新时刷新令牌
|
||
- POST /invalidate:撤销单个访问令牌
|
||
- POST /signout:基于邮箱+密码登出,撤销该用户所有令牌
|
||
|
||
文档将说明各端点的HTTP方法、请求体结构、响应数据格式、错误码含义,并结合会话数据存储机制(Redis)与TTL设置(15分钟),解释authenticate如何验证用户名/邮箱与密码、validate如何检查令牌有效性、refresh如何在令牌过期后重新生成新令牌。同时给出与内部用户系统的映射逻辑(如通过GetYggdrasilPasswordById查询密码)。
|
||
|
||
## 项目结构
|
||
Yggdrasil认证服务位于路由组“/api/v1/yggdrasil/authserver”,由处理器模块负责接收请求、调用服务层完成业务逻辑,并通过Redis与数据库进行会话与令牌持久化。
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "路由层"
|
||
R["routes.go<br/>注册/authserver路由"]
|
||
H["yggdrasil_handler.go<br/>认证处理器"]
|
||
end
|
||
subgraph "服务层"
|
||
S["yggdrasil_service.go<br/>会话与加入服务器逻辑"]
|
||
T["token_service.go<br/>令牌生成/验证/刷新/失效"]
|
||
end
|
||
subgraph "数据访问层"
|
||
YR["yggdrasil_repository.go<br/>Yggdrasil密码查询"]
|
||
end
|
||
subgraph "基础设施"
|
||
J["jwt.go<br/>JWT工具"]
|
||
RC["redis.go<br/>Redis客户端"]
|
||
RM["response.go<br/>通用响应结构"]
|
||
end
|
||
R --> H
|
||
H --> S
|
||
H --> T
|
||
S --> YR
|
||
T --> YR
|
||
H --> J
|
||
H --> RC
|
||
H --> RM
|
||
```
|
||
|
||
图表来源
|
||
- [routes.go](file://internal/handler/routes.go#L87-L111)
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L425)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L1-L202)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [jwt.go](file://pkg/auth/jwt.go#L1-L71)
|
||
- [redis.go](file://pkg/redis/redis.go#L1-L175)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L87-L111)
|
||
|
||
## 核心组件
|
||
- 路由注册:在路由中将/authserver下的五个端点挂载到对应处理器函数。
|
||
- 认证处理器:实现authenticate、validate、refresh、invalidate、signout等端点的请求解析、调用服务层、构造响应。
|
||
- 令牌服务:封装令牌生成、验证、刷新、失效等逻辑,维护令牌表与清理策略。
|
||
- 会话服务:封装JoinServer/HasJoinedServer,使用Redis存储会话数据,TTL为15分钟。
|
||
- 数据访问:通过repository层访问数据库,如查询Yggdrasil密码。
|
||
- 基础设施:JWT工具用于令牌签发与校验;Redis客户端用于会话数据持久化。
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L87-L111)
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L425)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L1-L202)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [jwt.go](file://pkg/auth/jwt.go#L1-L71)
|
||
- [redis.go](file://pkg/redis/redis.go#L1-L175)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
## 架构总览
|
||
下图展示/authserver端点的请求-处理-响应流程,以及与服务层、Redis、数据库的关系。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "yggdrasil_handler.go"
|
||
participant S as "yggdrasil_service.go"
|
||
participant T as "token_service.go"
|
||
participant YR as "yggdrasil_repository.go"
|
||
participant DB as "数据库"
|
||
participant RD as "Redis"
|
||
rect rgb(255,255,255)
|
||
Note over C,H : authenticate/validate/refresh/invalidate/signout
|
||
end
|
||
C->>H : POST /api/v1/yggdrasil/authserver/{endpoint}
|
||
H->>DB : 读取/写入数据如用户、角色、令牌
|
||
H->>RD : 读取/写入会话数据JoinServer/HasJoinedServer
|
||
H->>T : 调用令牌相关服务生成/验证/刷新/失效
|
||
H->>YR : 查询Yggdrasil密码凭据校验
|
||
T->>DB : 操作token表创建/删除/查询
|
||
S->>RD : Set/Get会话数据TTL=15分钟
|
||
H-->>C : JSON响应含状态码与数据
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L425)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L81-L202)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [redis.go](file://pkg/redis/redis.go#L60-L175)
|
||
|
||
## 详细组件分析
|
||
|
||
### 端点:POST /authenticate
|
||
- 方法与路径
|
||
- 方法:POST
|
||
- 路径:/api/v1/yggdrasil/authserver/authenticate
|
||
- 请求体结构
|
||
- agent:对象,描述客户端信息(通常包含名称与版本)
|
||
- clientToken:字符串,客户端令牌(可选)
|
||
- identifier:字符串,用户名或邮箱(必填)
|
||
- password:字符串,密码(必填)
|
||
- requestUser:布尔,是否返回用户属性(可选)
|
||
- 响应数据
|
||
- accessToken:字符串,访问令牌
|
||
- clientToken:字符串,客户端令牌
|
||
- availableProfiles:数组,可用角色列表(每个元素为序列化后的角色信息)
|
||
- selectedProfile:对象,当前选定的角色(可选)
|
||
- user:对象,当requestUser=true时返回(包含id与properties)
|
||
- 错误码
|
||
- 400:请求参数错误
|
||
- 403:用户名不存在或密码错误
|
||
- 500:服务器内部错误
|
||
- 处理流程要点
|
||
- 根据identifier判断是邮箱还是用户名,分别查询用户或角色
|
||
- 通过repository查询Yggdrasil密码并与请求密码比对
|
||
- 生成新令牌(包含accessToken、clientToken),并返回可用角色列表
|
||
- 如requestUser为true,附加用户属性
|
||
- 与内部用户系统映射
|
||
- 通过GetYggdrasilPasswordById查询Yggdrasil密码并与请求密码比对
|
||
- 通过GetUserIDByEmail或GetProfileByProfileName获取用户ID
|
||
- 通过GetProfileByUserId获取角色列表,自动选择唯一角色
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "Authenticate()"
|
||
participant DB as "数据库"
|
||
participant YR as "yggdrasil_repository.go"
|
||
participant T as "token_service.go"
|
||
C->>H : JSON请求identifier/password等
|
||
H->>DB : 根据identifier定位用户/角色
|
||
H->>YR : GetYggdrasilPasswordById(userId)
|
||
YR-->>H : 返回Yggdrasil密码
|
||
H->>H : 校验密码
|
||
H->>T : NewToken(userId, UUID, clientToken)
|
||
T-->>H : 返回accessToken/clientToken/availableProfiles
|
||
H-->>C : 200 JSONaccessToken/clientToken/availableProfiles/selectedProfile/user
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L246)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L1-L79)
|
||
- [token_service.go](file://internal/service/token_service.go#L24-L79)
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L246)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L1-L79)
|
||
- [token_service.go](file://internal/service/token_service.go#L24-L79)
|
||
|
||
### 端点:POST /validate
|
||
- 方法与路径
|
||
- 方法:POST
|
||
- 路径:/api/v1/yggdrasil/authserver/validate
|
||
- 请求体结构
|
||
- accessToken:字符串,访问令牌(必填)
|
||
- clientToken:字符串,客户端令牌(可选)
|
||
- 响应数据
|
||
- 当令牌有效:204 No Content(无body)
|
||
- 当令牌无效:403 Forbidden(valid=false)
|
||
- 处理流程要点
|
||
- 调用ValidToken校验accessToken与clientToken(若提供)
|
||
- 有效返回204,无效返回403
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "ValidToken()"
|
||
participant T as "token_service.go"
|
||
C->>H : JSON请求accessToken, clientToken
|
||
H->>T : ValidToken(accessToken, clientToken)
|
||
alt 有效
|
||
H-->>C : 204 No Content
|
||
else 无效
|
||
H-->>C : 403 {valid : false}
|
||
end
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L248-L267)
|
||
- [token_service.go](file://internal/service/token_service.go#L116-L141)
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L248-L267)
|
||
- [token_service.go](file://internal/service/token_service.go#L116-L141)
|
||
|
||
### 端点:POST /refresh
|
||
- 方法与路径
|
||
- 方法:POST
|
||
- 路径:/api/v1/yggdrasil/authserver/refresh
|
||
- 请求体结构
|
||
- accessToken:字符串,访问令牌(必填)
|
||
- clientToken:字符串,客户端令牌(可选)
|
||
- requestUser:布尔,是否返回用户属性(可选)
|
||
- selectedProfile:对象,包含id字段(可选)
|
||
- 响应数据
|
||
- accessToken:字符串,新的访问令牌
|
||
- clientToken:字符串,客户端令牌
|
||
- selectedProfile:对象,选定的角色(可选)
|
||
- user:对象,当requestUser=true时返回(包含id与properties)
|
||
- 处理流程要点
|
||
- 通过accessToken获取UUID与用户ID
|
||
- 校验selectedProfile(若提供)与用户匹配
|
||
- 调用RefreshToken生成新令牌,删除旧令牌
|
||
- 返回新令牌与可选数据
|
||
- 与内部用户系统映射
|
||
- 通过GetUUIDByAccessToken与GetUserIDByAccessToken获取用户与角色信息
|
||
- 通过ValidateProfileByUserID校验角色归属
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "RefreshToken()"
|
||
participant T as "token_service.go"
|
||
participant DB as "数据库"
|
||
C->>H : JSON请求accessToken, clientToken, selectedProfile, requestUser
|
||
H->>DB : GetUUIDByAccessToken / GetUserIDByAccessToken
|
||
H->>H : 校验selectedProfile归属
|
||
H->>T : RefreshToken(oldAccessToken, clientToken, selectedProfileID)
|
||
T-->>H : 返回newAccessToken, clientToken
|
||
H-->>C : 200 JSONnewAccessToken, clientToken, selectedProfile, user
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L269-L361)
|
||
- [token_service.go](file://internal/service/token_service.go#L151-L238)
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L269-L361)
|
||
- [token_service.go](file://internal/service/token_service.go#L151-L238)
|
||
|
||
### 端点:POST /invalidate
|
||
- 方法与路径
|
||
- 方法:POST
|
||
- 路径:/api/v1/yggdrasil/authserver/invalidate
|
||
- 请求体结构
|
||
- accessToken:字符串,访问令牌(必填)
|
||
- clientToken:字符串,客户端令牌(可选)
|
||
- 响应数据
|
||
- 204 No Content
|
||
- 处理流程要点
|
||
- 调用InvalidToken删除对应accessToken
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "InvalidToken()"
|
||
participant T as "token_service.go"
|
||
C->>H : JSON请求accessToken, clientToken
|
||
H->>T : InvalidToken(accessToken)
|
||
T-->>H : 删除完成
|
||
H-->>C : 204 No Content
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L363-L378)
|
||
- [token_service.go](file://internal/service/token_service.go#L240-L257)
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L363-L378)
|
||
- [token_service.go](file://internal/service/token_service.go#L240-L257)
|
||
|
||
### 端点:POST /signout
|
||
- 方法与路径
|
||
- 方法:POST
|
||
- 路径:/api/v1/yggdrasil/authserver/signout
|
||
- 请求体结构
|
||
- username:字符串,邮箱(必填)
|
||
- password:字符串,密码(必填)
|
||
- 响应数据
|
||
- 204 No Content
|
||
- 处理流程要点
|
||
- 校验邮箱格式
|
||
- 通过邮箱获取用户并查询Yggdrasil密码
|
||
- 对比请求密码与存储密码
|
||
- 调用InvalidUserTokens撤销该用户所有令牌
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "SignOut()"
|
||
participant DB as "数据库"
|
||
participant T as "token_service.go"
|
||
C->>H : JSON请求username, password
|
||
H->>H : 校验邮箱格式
|
||
H->>DB : GetUserByEmail / GetYggdrasilPasswordById
|
||
H->>H : 校验密码
|
||
H->>T : InvalidUserTokens(userId)
|
||
T-->>H : 删除完成
|
||
H-->>C : 204 No Content
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L380-L425)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [token_service.go](file://internal/service/token_service.go#L259-L277)
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L380-L425)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [token_service.go](file://internal/service/token_service.go#L259-L277)
|
||
|
||
### 会话数据存储与TTL(JoinServer/HasJoinedServer)
|
||
- 存储机制
|
||
- 使用Redis存储玩家加入服务器的会话数据,键规则为“Join_”前缀+serverId
|
||
- 数据结构包含accessToken、userName、selectedProfile、ip
|
||
- TTL设置
|
||
- 会话数据TTL为15分钟
|
||
- 读写流程
|
||
- JoinServer:校验参数与Token,获取角色信息,序列化会话数据并写入Redis
|
||
- HasJoinedServer:从Redis读取会话数据,反序列化后校验用户名与IP(可选)
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["进入JoinServer"]) --> Validate["校验serverId/accessToken/selectedProfile非空"]
|
||
Validate --> Format["格式化UUID与IP校验"]
|
||
Format --> GetToken["根据accessToken查询Token"]
|
||
GetToken --> MatchProfile["selectedProfile与Token绑定Profile匹配"]
|
||
MatchProfile --> LoadProfile["加载角色信息"]
|
||
LoadProfile --> BuildData["构建SessionData结构"]
|
||
BuildData --> Marshal["序列化SessionData"]
|
||
Marshal --> Store["Redis Set(key='Join_serverId', value, TTL=15m)"]
|
||
Store --> End(["完成"])
|
||
subgraph "HasJoinedServer"
|
||
HStart["读取serverId/username"] --> HLoad["Redis Get('Join_serverId')"]
|
||
HLoad --> Parse["反序列化SessionData"]
|
||
Parse --> CheckUser["校验userName匹配"]
|
||
CheckUser --> CheckIP{"提供IP?"}
|
||
CheckIP --> |是| IPMatch["校验IP匹配"]
|
||
CheckIP --> |否| Success["通过"]
|
||
IPMatch --> Success
|
||
end
|
||
```
|
||
|
||
图表来源
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L81-L202)
|
||
- [yggdrasil_service_test.go](file://internal/service/yggdrasil_service_test.go#L1-L351)
|
||
- [redis.go](file://pkg/redis/redis.go#L60-L175)
|
||
|
||
章节来源
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L19-L31)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L81-L202)
|
||
- [yggdrasil_service_test.go](file://internal/service/yggdrasil_service_test.go#L1-L351)
|
||
- [redis.go](file://pkg/redis/redis.go#L60-L175)
|
||
|
||
## 依赖关系分析
|
||
- 路由到处理器:/api/v1/yggdrasil/authserver/* 映射到yggdrasil_handler.go中的对应函数
|
||
- 处理器到服务:认证处理器调用令牌服务与会话服务
|
||
- 服务到仓库:令牌服务与会话服务通过repository层访问数据库
|
||
- 会话服务到Redis:JoinServer/HasJoinedServer直接使用Redis客户端
|
||
- 响应结构:统一使用通用响应结构(参考response.go)
|
||
|
||
```mermaid
|
||
graph LR
|
||
Routes["routes.go"] --> Handler["yggdrasil_handler.go"]
|
||
Handler --> TokenSvc["token_service.go"]
|
||
Handler --> YggSvc["yggdrasil_service.go"]
|
||
YggSvc --> Redis["redis.go"]
|
||
TokenSvc --> Repo["yggdrasil_repository.go"]
|
||
Handler --> Resp["response.go"]
|
||
```
|
||
|
||
图表来源
|
||
- [routes.go](file://internal/handler/routes.go#L87-L111)
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L425)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L1-L202)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [redis.go](file://pkg/redis/redis.go#L1-L175)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L87-L111)
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L425)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L1-L202)
|
||
- [yggdrasil_repository.go](file://internal/repository/yggdrasil_repository.go#L1-L17)
|
||
- [redis.go](file://pkg/redis/redis.go#L1-L175)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
## 性能考量
|
||
- Redis读写:JoinServer/HasJoinedServer使用GetBytes/Set,TTL为15分钟,适合短生命周期的会话数据
|
||
- 令牌清理:NewToken后异步触发CheckAndCleanupExcessTokens,限制用户最多保留10个令牌,降低数据库压力
|
||
- 超时控制:服务层对数据库查询设置默认超时,避免阻塞
|
||
- 并发安全:刷新令牌采用先创建新令牌再删除旧令牌的双写策略,减少事务复杂度
|
||
|
||
章节来源
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L81-L202)
|
||
- [token_service.go](file://internal/service/token_service.go#L81-L114)
|
||
- [redis.go](file://pkg/redis/redis.go#L60-L175)
|
||
|
||
## 故障排查指南
|
||
- 400 Bad Request
|
||
- 请求体解析失败或参数缺失
|
||
- 会话加入/验证参数缺失(serverId/username)
|
||
- 403 Forbidden
|
||
- 认证失败(用户名不存在或密码错误)
|
||
- 令牌无效或clientToken不匹配
|
||
- 用户与角色不匹配
|
||
- 500 Internal Server Error
|
||
- 生成令牌失败、读取/写入Redis失败、数据库查询异常
|
||
- 常见问题定位
|
||
- 确认identifier是否为邮箱或用户名
|
||
- 确认clientToken是否与accessToken匹配(validate/refresh)
|
||
- 检查Redis连接与TTL设置(JoinServer/HasJoinedServer)
|
||
- 检查用户角色与selectedProfile是否匹配(refresh)
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L425)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L81-L202)
|
||
- [yggdrasil_service_test.go](file://internal/service/yggdrasil_service_test.go#L1-L351)
|
||
|
||
## 结论
|
||
本认证服务围绕/authserver路由提供了完整的Yggdrasil认证能力,覆盖凭据认证、令牌验证、刷新、失效与登出。通过Redis实现15分钟TTL的会话数据存储,结合令牌服务的清理策略与严格的参数校验,确保系统在安全性与性能之间取得平衡。与内部用户系统的映射清晰,凭据校验通过getYggdrasilPasswordById完成,角色管理与令牌绑定完善。
|
||
|
||
## 附录
|
||
- 错误码对照
|
||
- 400:请求参数错误
|
||
- 403:权限不足/令牌无效/用户不匹配
|
||
- 500:服务器内部错误
|
||
- 响应结构
|
||
- 通用响应结构参考response.go中的Response/Error结构
|
||
- 会话数据结构
|
||
- SessionData包含accessToken、userName、selectedProfile、ip
|
||
|
||
章节来源
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
- [yggdrasil_service.go](file://internal/service/yggdrasil_service.go#L19-L31) |