ZBLOG

go-zero框架的 jwt-go api设计

在使用 go-zero 框架时,设计基于 JWT 的 API 通常包括用户注册、登录、JWT 生成和验证等功能。以下是一个示例 API 设计,用于实现这些功能。

示例 API 设计

  1. 依赖库: 确保已安装 jwt-go 库:
   go get github.com/dgrijalva/jwt-go
  1. API 路由: 使用 go-zero 的路由定义,创建如下几个路由:

    • POST /api/register: 用户注册
    • POST /api/login: 用户登录
    • GET /api/protected: 需要身份验证的保护资源
  2. 模型和请求参数: 首先定义一些数据结构来处理请求参数和响应结果。

// user.go
package model

type User struct {
    ID       int64  `json:"id"`
    Username string `json:"username"`
    Password string `json:"password"` // 请注意:真实应用中应存储哈希密码
}

type RegisterRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

type LoginRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

type LoginResponse struct {
    Token string `json:"token"`
}
  1. 服务端逻辑
package main

import (
    "github.com/dgrijalva/jwt-go"
    "net/http"
    "time"
)

var jwtSecret = []byte("your_secret_key")

func GenerateJWT(userId int64) (string, error) {
    claims := jwt.MapClaims{
        "user_id": userId,
        "exp":     time.Now().Add(time.Hour * 72).Unix(),
    }
    
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    
    return token.SignedString(jwtSecret)
}

// Mock database for demonstration purposes.
var users = map[string]string{}

func registerHandler(w http.ResponseWriter, r *http.Request) {
    var req RegisterRequest
    
    // Decode request body to req object (e.g., using json.NewDecoder)
    
	// Check if username already exists, and save the user data.
	users[req.Username] = req.Password // 不要在实际代码中明文存储密码,请使用哈希。
	httpx.OkJson(w, map[string]string{"message": "User registered successfully"})
}

func loginHandler(w http.ResponseWriter, r *http.Request) {
	var req LoginRequest
	
	// Decode request body to req object.
	
	if password, ok := users[req.Username]; ok && password == req.Password {
		token, err := GenerateJWT(int64(1)) // 实际情况应从数据库获取用户ID。
		if err != nil {
			http.Error(w, "Could not generate token", http.StatusInternalServerError)
			return
		}
		
		httpx.OkJson(w, LoginResponse{Token: token})
	} else {
		http.Error(w, "Invalid credentials", http.StatusUnauthorized)
	}
}

func protectedHandler(w http.ResponseWriter, r *http.Request) {
	tokenStr := r.Header.Get("Authorization")
	if tokenStr == "" {
	    http.Error(w, "Authorization header is required", http.StatusUnauthorized)
	    return
	}

	token, err := jwt.Parse(tokenStr[len("Bearer "):], func(token *jwt.Token) (interface{}, error) {
	    if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
	        return nil, ErrInvalidToken
	    }
	    return jwtSecret, nil
	})

	if err != nil || !token.Valid {
	    http.Error(w, "Invalid token", http.StatusUnauthorized)
	    return
	}
	
	w.Write([]byte("Welcome to the protected route!"))
}
  1. 主函数与路由配置
package main

import (
	"github.com/zeromicro/go-zero/rest"
)

func main() {
	r := rest.NewServer()

	r.POST("/api/register", registerHandler)
	r.POST("/api/login", loginHandler)
	r.GET("/api/protected", AuthMiddleware(protectedHandler))

	r.Start()
}

中间件函数(AuthMiddleware):

为了保护某些路由,需要创建一个中间件用于解析和验证 JWT。

func AuthMiddleware(next rest.HandlerFunc) rest.HandlerFunc {
	return func(ctx *rest.Context) error {
		tokenStr := ctx.Header["Authorization"]
		
		if len(tokenStr) == 0 || !strings.HasPrefix(tokenStr[0], "Bearer ") { 
			return rest.ErrUnauthorized 
		}
		
        // 提取 Bearer 后面的部分作为令牌字符串。
        tokenStr = strings.TrimPrefix(tokenStr[0], "Bearer ")

        _, err := ParseJWT(tokenStr)

        if err != nil { 
            return rest.ErrUnauthorized 
        }

        return next(ctx)
     }
}

总结

以上是一个简单的基于 JWT 身份验证的 API 示例,涵盖了用户注册、登录以及保护资源访问的基本流程。在真实场景中,你还需要加入错误处理、输入验证、安全性增强(如使用 HTTPS)、密码加密等措施。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=22337

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?