好吧,让我们说实话。安全性是一件大事,如果您正在构建 API,您不能让任何人闯入并开始弄乱您的数据。这就是 JWT(JSON Web 令牌) 发挥作用的地方。今天,我们通过添加基于 JWT 的身份验证来升级 Go API。
如果您一直在使用旧的 github.com/dgrijalva/jwt-go 软件包,那么是时候升级了。新标准是 github.com/golang-jwt/jwt/v4。
为什么要切换?
现在,让我们开始使用我们精美的新 JWT 库!
对于 JWT 新手:
现在您已经熟悉了,让我们深入研究代码!
我们将从上一篇文章中离开的地方继续。让我们更新 Go 模块并安装必要的软件包:
go get github.com/golang-jwt/jwt/v4 go get github.com/gorilla/mux
首先,我们将创建一个函数,在用户登录时生成 JWT 令牌。该令牌将包含用户名,并将使用密钥进行签名。
var jwtKey = []byte("my_secret_key") type Credentials struct { Username string `json:"username"` Password string `json:"password"` } type Claims struct { Username string `json:"username"` jwt.RegisteredClaims } func generateToken(username string) (string, error) { expirationTime := time.Now().Add(5 * time.Minute) claims := &Claims{ Username: username, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(expirationTime), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtKey) return tokenString, err }
此函数生成一个令牌,该令牌将在 5 分钟后过期,并使用 HS256 算法进行签名。
接下来,我们将构建一个登录端点,用户可以在其中发送凭据。如果登录信息检查通过,我们将生成一个 JWT 并将其通过 cookie 发回。
func login(w http.ResponseWriter, r *http.Request) { var creds Credentials err := json.NewDecoder(r.Body).Decode(&creds) if err != nil { w.WriteHeader(http.StatusBadRequest) return } if creds.Username != "admin" || creds.Password != "password" { w.WriteHeader(http.StatusUnauthorized) return } token, err := generateToken(creds.Username) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } http.SetCookie(w, &http.Cookie{ Name: "token", Value: token, Expires: time.Now().Add(5 * time.Minute), }) }
现在,我们需要一个中间件函数来验证 JWT 令牌,然后才能允许访问受保护的路由。
func authenticate(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c, err := r.Cookie("token") if err != nil { if err == http.ErrNoCookie { w.WriteHeader(http.StatusUnauthorized) return } w.WriteHeader(http.StatusBadRequest) return } tokenStr := c.Value claims := &Claims{} tkn, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) { return jwtKey, nil }) if err != nil || !tkn.Valid { w.WriteHeader(http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) }
此中间件检查请求是否具有有效的 JWT 令牌。如果不是,它会返回未经授权的响应。
现在,让我们应用我们的身份验证中间件来保护 /books 路由:
func main() { r := mux.NewRouter() r.HandleFunc("/login", login).Methods("POST") r.Handle("/books", authenticate(http.HandlerFunc(getBooks))).Methods("GET") fmt.Println("Server started on port :8000") log.Fatal(http.ListenAndServe(":8000", r)) }
curl -X POST http://localhost:8000/login -d '{"username":"admin", "password":"password"}' -H "Content-Type: application/json"
curl --cookie "token=<your_token>" http://localhost:8000/books
如果令牌有效,您将获得访问权限。如果没有,您将收到“401 Unauthorized”。
下次,我们将把 API 连接到数据库来管理用户凭据和存储数据。更多精彩敬请期待!
以上是使用 JWT 身份验证保护您的 Go API的详细内容。更多信息请关注PHP中文网其他相关文章!