在Go-Zero框架中使用JWT进行身份验证是一个常见的需求。Go-Zero框架提供了一些内置的功能来处理JWT,简化了在API中实施身份验证的过程。下面是如何在Go-Zero框架中实现JWT身份验证的基本步骤。
1. 安装Go-Zero
首先,你需要安装Go-Zero。如果还没有安装,可以通过以下命令进行安装:
go get -u github.com/zeromicro/go-zero
2. 创建项目结构
假设你的项目结构如下:
your_project/
├── api/
│ └── your_api.api
├── logic/
│ ├── loginlogic.go
│ └── protectedlogic.go
├── middleware/
│ └── jwtmiddleware.go
├── model/
│ └── usermodel.go
└── main.go
3. 定义API文件
在api/your_api.api
文件中定义API接口:
syntax = "proto3";
package api;
service YourService {
rpc Login(LoginRequest) returns (LoginResponse);
rpc Protected(ProtectedRequest) returns (ProtectedResponse);
}
message LoginRequest {
string username = 1;
string password = 2;
}
message LoginResponse {
string token = 1;
}
message ProtectedRequest {}
message ProtectedResponse {
string message = 1;
}
4. 自动生成代码
使用以下命令生成代码:
goctl api protoc api/your_api.api --go_out=./ --go-grpc_out=./
5. 编写逻辑
登录逻辑(logic/loginlogic.go
)
在这里,我们将创建一个用户并返回JWT令牌:
package logic
import (
"context"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/zeromicro/go-zero/core/logx"
"your_project/api"
)
type LoginLogic struct {
ctx context.Context
}
var secretKey = []byte("your_secret_key")
func (l *LoginLogic) Login(req *api.LoginRequest) (*api.LoginResponse, error) {
// TODO: Validate username and password with your user model or database.
if req.Username == "user" && req.Password == "pass" { // 示例用法,实际应验证数据库用户。
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": req.Username,
"exp": time.Now().Add(time.Hour * 72).Unix(),
})
tokenString, err := token.SignedString(secretKey)
if err != nil {
logx.Error(err)
return nil, err
}
return &api.LoginResponse{Token: tokenString}, nil
}
return nil, nil // 应该返回相应错误提示。
}
受保护逻辑(logic/protectedlogic.go
)
确保用户具有有效的JWT才能访问此逻辑:
package logic
import (
"context"
"github.com/dgrijalva/jwt-go"
"github.com/zeromicro/go-zero/core/logx"
"your_project/api"
)
type ProtectedLogic struct {
ctx context.Context
}
func (l *ProtectedLogic) Protected(req *api.ProtectedRequest) (*api.ProtectedResponse, error) {
authHeader := l.ctx.Value("Authorization").(string)
if authHeader == "" || len(authHeader) < 7 || authHeader[:6] != "Bearer" {
return nil, errors.New("Unauthorized")
}
tokenString := authHeader[7:]
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return secretKey, nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
logx.Infof("User %s accessed protected route", claims["username"])
return &api.ProtectedResponse{Message: "This is a protected route"}, nil
} else {
return nil, errors.New("Unauthorized")
}
}
6. 编写中间件(可选)
你可以编写一个中间件来解析JWT并将其添加到上下文中。这使得你可以轻松地从请求上下文中提取认证信息。
中间件 (middleware/jwtmiddleware.go
)
package middleware
import (
"net/http"
"github.com/dgrijalva/jwt-go"
)
func JwtMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" || len(authHeader) < 7 || authHeader[:6] != "Bearer" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
tokenString := authHeader[7:]
_, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error){
return []byte("your_secret_key"), nil
})
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next(w,r)
}
}
7. 主函数 (main.go
)
最终,在主函数中设置路由和服务启动。
package main
import (
"net/http"
"github.com/zeromicro/go-zero/rest"
. "your_project/api"
)
func main() {
routes := rest.MustNewServer(rest.RestConf{})
defer routes.Stop()
routes.AddRoute(rest.Route{
Method: http.MethodPost,
Path: "/login",
Handler: JwtMiddleware(NewYourService().Login),
})
routes.AddRoute(rest.Route{
Method: http.MethodGet,
Path: "/protected",
Handler: JwtMiddleware(NewYourService().Protected),
})
routes.Start()
}
这样,你就完成了在 Go-Zero 框架下实现 JWT 身份验证 API 的基本示例。确保测试和进一步增强安全性,例如密码哈希、存储与用户模型等。
内容由零声教学AI助手提供,问题来源于学员提问