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" ) type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } type TokenInfo struct { Token string `json:"access_token"` } type UserInfo struct { Name string `json:"name"` Introduction string `json:"introduction"` Avatar string `json:"avatar"` Roles []string `json:"roles"` } type LoginResponse struct { Code int `json:"code"` Message string `json:"message"` Date string `json:"date"` Data TokenInfo `json:"data"` } type LogutResponse struct { Code int `json:"code"` Message string `json:"message"` } type UserInfoResponse struct { Code int `json:"code"` Message string `json:"message"` Date string `json:"date"` 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) { // 解析CSR请求 var loginRequest LoginRequest if err := json.NewDecoder(r.Body).Decode(&loginRequest); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // 检查用户 if !CheckUser(loginRequest) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // 生成Token token, err := utils.GenerateRandomString(32) if err != nil { http.Error(w, fmt.Sprintf("Failed to generate token: %v", err), http.StatusInternalServerError) return } // 返回Token信息 w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusOK) response := LoginResponse{ Code: http.StatusOK, Message: "Login successful", Date: time.Now().Format(time.RFC3339), Data: TokenInfo{Token: token}, } json.NewEncoder(w).Encode(response) } func Logout(w http.ResponseWriter, r *http.Request) { // 这里可以添加注销逻辑,例如清除用户会话等 w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusOK) response := LogutResponse{ Code: http.StatusOK, Message: "Logout successful", } json.NewEncoder(w).Encode(response) } // CheckBlacklist 处理黑名单查询请求 func CheckUser(login LoginRequest) bool { if login.Username == "admin" && login.Password == "111111" { return true } return false } func GetUserInfo(w http.ResponseWriter, r *http.Request) { // 假设用户信息存储在某个地方,这里直接返回一个示例用户信息 userInfo := UserInfo{ Name: "Admin User", Introduction: "This is an admin", Avatar: "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif", Roles: []string{"admin"}, } // 返回Token信息 w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusOK) response := UserInfoResponse{ Code: http.StatusOK, Message: "Login successful", Date: time.Now().Format(time.RFC3339), Data: userInfo, } 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) } }