You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang实现:动态传递用户名密码JSON请求体调用Post API获取JWT

改进方案:动态获取用户信息请求JWT令牌

核心改进思路

  • 定义请求体结构体替代硬编码JSON字符串,实现动态赋值
  • 重构认证函数,通过参数接收用户登录信息,返回令牌与错误,避免全局变量污染
  • 添加HTTP登录接口,适配多用户Web应用场景,接收客户端传入的用户信息
  • 完善错误处理逻辑,替换废弃的标准库API

改进后完整代码

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	"github.com/joho/godotenv"
)

// 登录请求结构体,对应认证API所需的参数字段
type LoginRequest struct {
	Name  string `json:"name"`
	Pwd   string `json:"pwd"`
	HName string `json:"hName"`
}

// 认证响应结构体,解析API返回的令牌数据
type AuthorizationResponse struct {
	AuthorizationToken string `json:"authorizationToken"`
	ExpiresTimestamp   string `json:"expiresTimestamp"`
}

func main() {
	// 加载环境变量
	if err := godotenv.Load(".env"); err != nil {
		log.Fatalf("加载.env文件失败: %v", err)
	}

	// 注册登录接口,供客户端调用
	http.HandleFunc("/login", loginHandler)
	log.Println("服务启动,监听端口8080")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatalf("服务启动失败: %v", err)
	}
}

// 登录接口处理函数,接收客户端提交的用户信息
func loginHandler(w http.ResponseWriter, r *http.Request) {
	// 仅允许POST请求
	if r.Method != http.MethodPost {
		http.Error(w, "仅支持POST请求", http.StatusMethodNotAllowed)
		return
	}

	// 解析客户端传入的登录参数
	var req LoginRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "请求体解析失败: "+err.Error(), http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	// 调用认证接口获取JWT令牌
	token, err := getAuthToken(req)
	if err != nil {
		http.Error(w, "获取令牌失败: "+err.Error(), http.StatusInternalServerError)
		return
	}

	// 将令牌返回给客户端
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{"token": token})
}

// 重构后的认证函数,动态接收用户信息并返回令牌
func getAuthToken(loginReq LoginRequest) (string, error) {
	authURL := os.Getenv("authorizationUrl")
	if authURL == "" {
		return "", fmt.Errorf("authorizationUrl环境变量未配置")
	}

	// 将登录参数序列化为JSON请求体
	requestBody, err := json.Marshal(loginReq)
	if err != nil {
		return "", fmt.Errorf("序列化请求体失败: %v", err)
	}

	// 发送POST请求到认证API
	resp, err := http.Post(authURL, "application/json", io.NopCloser(bytes.NewBuffer(requestBody)))
	if err != nil {
		return "", fmt.Errorf("发送认证请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码是否正常
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return "", fmt.Errorf("认证接口返回错误状态码: %d,响应内容: %s", resp.StatusCode, string(body))
	}

	// 读取并解析响应体
	content, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应体失败: %v", err)
	}

	var authResp AuthorizationResponse
	if err := json.Unmarshal(content, &authResp); err != nil {
		return "", fmt.Errorf("解析认证响应失败: %v", err)
	}

	if authResp.AuthorizationToken == "" {
		return "", fmt.Errorf("认证接口未返回有效令牌")
	}

	return authResp.AuthorizationToken, nil
}

关键改动说明

  1. 请求体结构化:新增LoginRequest结构体,把硬编码的JSON字段映射为Go结构体字段,支持动态传入不同用户的登录信息。
  2. 函数解耦:getAuthToken不再依赖全局变量,通过参数接收用户信息并返回令牌与错误,每个请求独立处理,适配多用户并发场景。
  3. Web场景适配:添加loginHandler作为HTTP接口,客户端可通过POST请求提交用户名密码,接口完成认证后返回JWT令牌,符合Web应用的使用逻辑。
  4. 错误处理强化:完善了环境变量校验、HTTP响应状态码检查、序列化/反序列化错误捕获,避免静默失败,便于问题排查。
  5. 废弃API替换:将已废弃的ioutil.ReadAll替换为标准库的io.ReadAll,符合Go最新版本的API规范。

内容的提问来源于stack exchange,提问作者user12396077

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 01:36:59