对接统一登录认证

This commit is contained in:
wangjianhong
2025-07-23 22:17:47 +08:00
parent 5e4e272b3a
commit e7442ae419
48 changed files with 2940 additions and 3067 deletions

View File

@@ -1,10 +1,17 @@
package handlers
import (
"bytes"
"ca-mini/internal/config"
"ca-mini/pkg/utils"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"
)
@@ -14,7 +21,7 @@ type LoginRequest struct {
}
type TokenInfo struct {
Token string `json:"token"`
Token string `json:"access_token"`
}
type UserInfo struct {
@@ -42,6 +49,21 @@ type UserInfoResponse struct {
Data UserInfo `json:"data"`
}
// Token 是返回的 Token 结构体
type Token struct {
TokenType string `json:"token_type,omitempty"`
ExpiresIn int64 `json:"expires_in,omitempty"`
AccessToken string `json:"access_token,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
}
type TokenResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Date string `json:"date"`
Data Token `json:"data"`
}
// IssueCertificate 处理证书签发请求
func Login(w http.ResponseWriter, r *http.Request) {
@@ -114,3 +136,88 @@ func GetUserInfo(w http.ResponseWriter, r *http.Request) {
}
json.NewEncoder(w).Encode(response)
}
func AuthCallBack(w http.ResponseWriter, r *http.Request) {
cfg, err := config.Load()
if err != nil {
log.Fatalf("failed to load oauth config: %v", err)
}
// 从 URL 中提取 authorization code
code := r.URL.Query().Get("code")
if code == "" {
http.Error(w, "Missing authorization code", http.StatusBadRequest)
return
}
// 构造 Basic Auth header
auth := cfg.OAuth.CLIENT_ID + ":" + cfg.OAuth.CLIENT_SECRET
authHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
// 构造请求体
formData := url.Values{}
formData.Add("grant_type", "authorization_code")
formData.Add("redirect_uri", cfg.OAuth.REDIRECT_URI)
formData.Add("client_id", cfg.OAuth.CLIENT_ID)
formData.Add("code", code)
// 创建请求
tokenURL := cfg.OAuth.AUTHORIZATION_SERVER_HOST + cfg.OAuth.TOKEN_URL
req, err := http.NewRequestWithContext(context.Background(), "POST", tokenURL, bytes.NewBufferString(formData.Encode()))
if err != nil {
log.Printf("Error creating request: %v", err)
http.Error(w, "Failed to create token request", http.StatusInternalServerError)
return
}
// 设置请求头
req.Header.Set("Authorization", authHeader)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Printf("Unexpected error while fetching token: %v", err)
http.Error(w, "Failed to fetch token", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Error reading response body: %v", err)
http.Error(w, "Failed to read token response", http.StatusInternalServerError)
return
}
if resp.StatusCode != http.StatusOK {
log.Printf("Error while fetching token: %s, response body: %s", resp.Status, body)
http.Error(w, fmt.Sprintf("Token request failed: %s", resp.Status), resp.StatusCode)
return
}
// 解析 JSON 到 Token 结构体
var token Token
if err := json.Unmarshal(body, &token); err != nil {
log.Printf("Error unmarshalling token response: %v", err)
http.Error(w, "Failed to parse token response", http.StatusInternalServerError)
return
}
// 返回 Token 信息
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
response := TokenResponse{
Code: http.StatusOK,
Message: "Login successful",
Date: time.Now().Format(time.RFC3339),
Data: token,
}
if err := json.NewEncoder(w).Encode(response); err != nil {
log.Printf("Error encoding JSON response: %v", err)
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
}
}