目录
使用 Golang 实现 JWT? Authentication 认证
HTTP API 认证技术主要用于验证客户端身份,并确保只有经过授权的实体才能访问受保护的资源。随着安全需求的日益增长,API 认证技术也在不断发展和演进。本文将详细讲解 Digest Access Authentication 认证技术。
JWT(JSON Web Tokens)是一种开放标准(RFC 7519),定义了一种紧凑的、自包含的格式,用于实现网络应用程序中的身份验证和授权机制。
一个 JWT 通常由三部分组成,分别是头部(Header)、负载(Payload)和签名(Signature)。
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"time"
)
var jwtKey = []byte("my_secret_key")
type Claims struct {
Username string `json:"username"`
jwt.StandardClaims
}
func GenerateJWT(username string) (string, error) {
expirationTime := time.Now().Add(5 * time.Minute)
claims := &Claims{
Username: username,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
return "", err
}
return tokenString, nil
}
func main() {
tokenString, err := GenerateJWT("user1")
if err != nil {
fmt.Println("Error generating token:", err)
return
}
fmt.Println("Generated Token:", tokenString)
}
定义了一个 Claims 结构体,包含用户的用户名和标准 JWT 声明,使用了一个简单的密钥来签名令牌,并设置了5分钟的过期时间。
func ValidateJWT(tokenString string) (*Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil {
return nil, err
}
if !token.Valid {
return nil, fmt.Errorf("invalid token")
}
return claims, nil
}
package main
import (
"encoding/json"
"fmt"
"github.com/dgrijalva/jwt-go"
"net/http"
"time"
)
var jwtKey = []byte("my_secret_key")
type Claims struct {
Username string `json:"username"`
jwt.StandardClaims
}
func GenerateJWT(username string) (string, error) {
expirationTime := time.Now().Add(5 * time.Minute)
claims := &Claims{
Username: username,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
return "", err
}
return tokenString, nil
}
func ValidateJWT(tokenString string) (*Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil {
return nil, err
}
if !token.Valid {
return nil, fmt.Errorf("invalid token")
}
return claims, nil
}
func Login(w http.ResponseWriter, r *http.Request) {
// 假设我们从请求中获取用户名和密码
username := r.FormValue("username")
// password = r.FormValue("password")
// 这里应该验证用户名和密码的正确性
// 为了示例,我们假设任何用户名密码组合都是有效的
tokenString, err := GenerateJWT(username)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write([]byte(tokenString))
}
func Home(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
claims, err := ValidateJWT(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
json.NewEncoder(w).Encode(claims)
}
func main() {
http.HandleFunc("/login", Login)
http.HandleFunc("/home", Home)
http.ListenAndServe(":8080", nil)
}
有两个路由处理函数,Login 函数生成 JWT 并返回给用户。Home 函数则需要用户将 JWT作为 Authorization(也可以使用其他字段) 头部发送,以验证用户的请求。
JWT 的优点如下:
JWT 的缺点如下:
JWT 是一种非常灵活的认证方式,可以用于多种场景,例如用户认证、服务间 API 调用认证等。但是 JWT 也存在固有的缺点,需要根据自己的使用场景做出最合适的选择。