| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package middleware
- import (
- "errors"
- "fmt"
- "github.com/gin-gonic/gin"
- "github.com/golang-jwt/jwt/v5"
- "go_server/base/config"
- "go_server/base/core"
- "go_server/model/common/response"
- "net/http"
- "strings"
- "time"
- )
- const AuthorizationHeader = "Authorization"
- // JwtMiddleware JWT中间件, 强制要求用户登录
- func JwtMiddleware() gin.HandlerFunc {
- return func(c *gin.Context) {
- tokenString := c.GetHeader(AuthorizationHeader)
- if tokenString == "" {
- c.AbortWithStatusJSON(http.StatusUnauthorized, response.ErrorObjByCode(response.ResponseCodeMissAuthToken))
- return
- }
- // 解析JWT
- member, err := ParseJWT(tokenString)
- if err != nil || member == nil || member.ExpiresAt.Time.Before(time.Now()) {
- c.AbortWithStatusJSON(http.StatusUnauthorized, response.ErrorObjByCode(response.ResponseCodeTokenInvalid))
- return
- }
- // token有效,设置用户信息到上下文
- setClaimsToContext(c, member)
- // 继续执行
- c.Next()
- }
- }
- // setClaimsToContext 设置用户信息到上下文
- func setClaimsToContext(c *gin.Context, member *MyClaims) {
- c.Set("userId", member.UserID)
- c.Set("roleId", member.RoleId)
- c.Set("exp", member.ExpiresAt)
- c.Set("issuer", member.Issuer)
- }
- // OptionalJwtMiddleware 允许用户携带 JWT,但不强制要求登录
- func OptionalJwtMiddleware() gin.HandlerFunc {
- return func(c *gin.Context) {
- tokenString := c.GetHeader(AuthorizationHeader)
- if tokenString != "" {
- // 解析JWT
- member, err := ParseJWT(tokenString)
- if err == nil {
- if member != nil {
- setClaimsToContext(c, member)
- }
- } else {
- core.Log.Infof("OptionalJwtMiddleware:%s", err.Error())
- }
- }
- c.Next()
- }
- }
- type Member struct {
- ID int64
- RoleId int64
- }
- // Secret key used to sign the JWT token (In production, use environment variables to keep it secure)
- var jwtSecretStr = "admin.secret.1234565"
- var jwtSecretByte = []byte(jwtSecretStr)
- var jwtExpireDuration = int64(24) // in seconds
- var jwtIssuer = "issuer"
- // MyClaims 定义了JWT中的自定义声明
- type MyClaims struct {
- UserID int64 `json:"userId"`
- RoleId int64 `json:"roleId"`
- jwt.RegisteredClaims
- }
- func init() {
- jwtSecretStr = config.EnvConf().JWT.SigningKey
- jwtSecretByte = []byte(jwtSecretStr)
- jwtExpireDuration = config.EnvConf().JWT.ExpiresTime
- jwtIssuer = config.EnvConf().JWT.Issuer
- }
- // GenerateJWT 根据用户信息生成JWT
- func GenerateJWT(user Member) (string, error) {
- // 设置JWT的过期时间
- d := time.Duration(jwtExpireDuration) * time.Hour
- expirationTime := time.Now().Add(d)
- // 创建JWT的声明
- claims := MyClaims{
- UserID: user.ID,
- RoleId: user.RoleId,
- RegisteredClaims: jwt.RegisteredClaims{
- ID: fmt.Sprintf("%d", user.ID), // 设置ID
- ExpiresAt: jwt.NewNumericDate(expirationTime), // 设置过期时间
- Issuer: jwtIssuer, // 设置签发者
- },
- }
- // 使用HS256算法签署JWT
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- // 生成并返回签名后的JWT字符串
- tokenString, err := token.SignedString(jwtSecretByte)
- if err != nil {
- return "", err
- }
- return tokenString, nil
- }
- // ParseJWT 解析和验证JWT
- func ParseJWT(tokenString string) (*MyClaims, error) {
- // 定义一个空的声明对象
- claims := &MyClaims{}
- // 去掉 "Bearer " 部分
- tokenString = strings.TrimPrefix(tokenString, "Bearer ")
- // 解析JWT
- token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
- // 验证签名算法
- if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
- return nil, errors.New("unexpected signing method")
- }
- return jwtSecretByte, nil
- })
- if err != nil || !token.Valid {
- return nil, errors.New("invalid token")
- }
- return claims, nil
- }
- // 解析gin上下文中的用户信息
- func ParseUser(c *gin.Context) *MyClaims {
- userId, _ := c.Get("userId")
- roleId, _ := c.Get("openId")
- issuer, _ := c.Get("issuer")
- claims := &MyClaims{
- UserID: userId.(int64),
- RoleId: roleId.(int64),
- RegisteredClaims: jwt.RegisteredClaims{
- Issuer: issuer.(string),
- },
- }
- return claims
- }
|