在使用 go-zero
框架时,设计基于 JWT 的 API 通常包括用户注册、登录、JWT 生成和验证等功能。以下是一个示例 API 设计,用于实现这些功能。
示例 API 设计
- 依赖库:
确保已安装
jwt-go
库:
go get github.com/dgrijalva/jwt-go
API 路由: 使用
go-zero
的路由定义,创建如下几个路由:POST /api/register
: 用户注册POST /api/login
: 用户登录GET /api/protected
: 需要身份验证的保护资源
模型和请求参数: 首先定义一些数据结构来处理请求参数和响应结果。
// 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"`
}
- 服务端逻辑:
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!"))
}
- 主函数与路由配置:
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助手提供,问题来源于学员提问