83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"kra/app/system/internal/biz"
|
|
"kra/app/system/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"golang.org/x/sync/singleflight"
|
|
)
|
|
|
|
const claimsKey = "admin_claims"
|
|
|
|
var refreshTokens singleflight.Group
|
|
|
|
func Auth(auth *service.AuthService) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
token := c.GetHeader("x-token")
|
|
if token == "" {
|
|
token, _ = c.Cookie("x-token")
|
|
}
|
|
if token == "" {
|
|
NoAuth(c, "未登录或非法访问,请登录")
|
|
return
|
|
}
|
|
value, err, _ := refreshTokens.Do(token, func() (any, error) {
|
|
return auth.AuthenticateToken(c.Request.Context(), token)
|
|
})
|
|
if err != nil {
|
|
message := "无法处理此token"
|
|
switch {
|
|
case errors.Is(err, biz.ErrTokenExpired):
|
|
message = "登录已过期,请重新登录"
|
|
case errors.Is(err, biz.ErrTokenMalformed):
|
|
message = "这不是一个token"
|
|
case errors.Is(err, biz.ErrTokenSignatureInvalid):
|
|
message = "无效签名"
|
|
case errors.Is(err, biz.ErrTokenNotValidYet):
|
|
message = "token尚未激活"
|
|
case errors.Is(err, biz.ErrTokenDisabled):
|
|
message = "您的帐户异地登陆或令牌失效"
|
|
}
|
|
SetTokenCookie(c, "", -1)
|
|
NoAuth(c, message)
|
|
return
|
|
}
|
|
authentication := value.(*biz.TokenAuthentication)
|
|
if authentication.Refreshed != nil {
|
|
c.Header("new-token", authentication.Refreshed.Value)
|
|
c.Header("new-expires-at", strconv.FormatInt(authentication.Refreshed.ExpiresAt.Unix(), 10))
|
|
SetTokenCookie(c, authentication.Refreshed.Value, int(authentication.Refreshed.TTL.Seconds()))
|
|
}
|
|
c.Set(claimsKey, authentication.Claims)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func Claims(c *gin.Context) *biz.AuthClaims {
|
|
value, _ := c.Get(claimsKey)
|
|
claims, _ := value.(*biz.AuthClaims)
|
|
return claims
|
|
}
|
|
|
|
func MustChangePassword() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
claims := Claims(c)
|
|
if claims == nil || !claims.MustChangePwd {
|
|
c.Next()
|
|
return
|
|
}
|
|
path := strings.TrimSuffix(c.Request.URL.Path, "/")
|
|
if strings.HasSuffix(path, "/user/changePassword") || strings.HasSuffix(path, "/user/getUserInfo") || strings.HasSuffix(path, "/jwt/jsonInBlacklist") {
|
|
c.Next()
|
|
return
|
|
}
|
|
c.AbortWithStatusJSON(http.StatusConflict, Response{Code: CodePasswordChangeRequired, Data: gin.H{"needChangePassword": true}, Msg: "密码已过期,请先修改密码"})
|
|
}
|
|
}
|