| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package utils
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "time"
- "github.com/beego/beego/v2/server/web"
- )
- // TokenUserInfo 从token验证API返回的用户信息
- type TokenUserInfo struct {
- AccountID string `json:"accountID"`
- ID int64 `json:"id"`
- Name string `json:"name"`
- UserCode string `json:"userCode"`
- ContactNumber string `json:"contactNumber"`
- TokenType string `json:"token_type"`
- Exp int64 `json:"exp"`
- Iat int64 `json:"iat"`
- }
- // VerifyToken 验证token并返回用户信息
- func VerifyToken(token string) (*TokenUserInfo, error) {
- if token == "" {
- return nil, fmt.Errorf("token不能为空")
- }
- // 从配置文件读取token验证API URL
- authAPIURL, err := web.AppConfig.String("auth_api_url")
- if err != nil || authAPIURL == "" {
- // 如果配置不存在,使用默认值
- authAPIURL = "https://aqai.shudaodsj.com:22000/api/auth/verify"
- }
- fmt.Printf("🔐 开始验证Token...\n")
- fmt.Printf(" 验证API: %s\n", authAPIURL)
- // 构建请求体
- requestBody := map[string]string{
- "token": token,
- }
- jsonData, err := json.Marshal(requestBody)
- if err != nil {
- return nil, fmt.Errorf("序列化请求体失败: %v", err)
- }
- // 创建HTTP请求
- req, err := http.NewRequest("POST", authAPIURL, bytes.NewBuffer(jsonData))
- if err != nil {
- return nil, fmt.Errorf("创建请求失败: %v", err)
- }
- req.Header.Set("Content-Type", "application/json")
- // 重要:认证API需要在请求头中也携带 Authorization
- req.Header.Set("Authorization", "Bearer "+token)
- fmt.Printf(" 请求头 Authorization: Bearer %s...\n", token[:20])
- // 发送请求
- client := &http.Client{Timeout: 10 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- fmt.Printf("❌ 请求token验证API失败: %v\n", err)
- return nil, fmt.Errorf("请求token验证API失败: %v", err)
- }
- defer resp.Body.Close()
- // 读取响应体
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- fmt.Printf("❌ 读取响应失败: %v\n", err)
- return nil, fmt.Errorf("读取响应失败: %v", err)
- }
- fmt.Printf(" 响应状态码: %d\n", resp.StatusCode)
- fmt.Printf(" 响应内容: %s\n", string(body))
- // 检查HTTP状态码
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("token验证失败,状态码: %d, 响应: %s", resp.StatusCode, string(body))
- }
- // 解析响应
- var userInfo TokenUserInfo
- if err := json.Unmarshal(body, &userInfo); err != nil {
- fmt.Printf("❌ 解析响应失败: %v\n", err)
- return nil, fmt.Errorf("解析token验证响应失败: %v", err)
- }
- // 检查token是否过期
- if userInfo.Exp > 0 && time.Now().Unix() > userInfo.Exp {
- fmt.Printf("❌ Token已过期 (exp: %d, now: %d)\n", userInfo.Exp, time.Now().Unix())
- return nil, fmt.Errorf("token已过期")
- }
- fmt.Printf("✅ Token验证成功\n")
- return &userInfo, nil
- }
- // GetUserInfoFromToken 从请求头中获取token并验证,返回用户信息
- func GetUserInfoFromToken(headerFunc func(string) string) (*TokenUserInfo, error) {
- // 尝试从多个可能的header字段获取token
- token := headerFunc("token")
- fmt.Print("token", token)
- if token == "" {
- token = headerFunc("Token")
- }
- if token == "" {
- token = headerFunc("Authorization")
- // 如果是Bearer token格式,去掉"Bearer "前缀
- if len(token) > 7 && token[:7] == "Bearer " {
- token = token[7:]
- }
- }
- if token == "" {
- return nil, fmt.Errorf("请求头中未找到token")
- }
- return VerifyToken(token)
- }
- // GetUserInfoFromContext 从Beego Context中获取已验证的用户信息
- // 该函数假定中间件已经验证过token并将用户信息存储在context中
- func GetUserInfoFromContext(input interface{}) (*TokenUserInfo, error) {
- // 添加调试信息
- fmt.Printf("\n🔍 [GetUserInfoFromContext] 开始解析用户信息\n")
- fmt.Printf(" 输入类型: %T\n", input)
- fmt.Printf(" 输入值: %+v\n", input)
- // 检查input是否为nil
- if input == nil {
- fmt.Printf("❌ [GetUserInfoFromContext] input为nil\n\n")
- return nil, fmt.Errorf("未找到用户信息,context中userInfo为nil,请确保已经过token认证")
- }
- // 从context中获取userInfo
- userInfo, ok := input.(*TokenUserInfo)
- if !ok {
- fmt.Printf("❌ [GetUserInfoFromContext] 类型断言失败,期望 *TokenUserInfo,实际得到 %T\n\n", input)
- return nil, fmt.Errorf("用户信息类型错误,期望 *TokenUserInfo,实际得到 %T", input)
- }
- if userInfo == nil {
- fmt.Printf("❌ [GetUserInfoFromContext] userInfo为nil\n\n")
- return nil, fmt.Errorf("用户信息为空")
- }
- fmt.Printf("✅ [GetUserInfoFromContext] 成功解析用户信息\n")
- fmt.Printf(" - AccountID: %s\n", userInfo.AccountID)
- fmt.Printf(" - ID: %d\n", userInfo.ID)
- fmt.Printf(" - Name: %s\n\n", userInfo.Name)
- return userInfo, nil
- }
|