package auth import ( "encoding/json" "github.com/dgrijalva/jwt-go" "gxt-file-server/app/errors" "time" ) // TokenInfo 令牌信息 type TokenInfo interface { // GetAccessToken 获取访问令牌 GetAccessToken() string // GetTokenType 获取令牌类型 GetTokenType() string // GetExpiresAt 获取令牌到期时间戳 GetExpiresAt() int64 // EncodeToJSON JSON编码 EncodeToJSON() ([]byte, error) } // tokenInfo 令牌信息 type tokenInfo struct { AccessToken string `json:"access_token"` // 访问令牌 TokenType string `json:"token_type"` // 令牌类型 ExpiresAt int64 `json:"expires_at"` // 令牌到期时间 } func (t *tokenInfo) GetAccessToken() string { return t.AccessToken } func (t *tokenInfo) GetTokenType() string { return t.TokenType } func (t *tokenInfo) GetExpiresAt() int64 { return t.ExpiresAt } func (t *tokenInfo) EncodeToJSON() ([]byte, error) { return json.Marshal(t) } type options struct { signingMethod jwt.SigningMethod signingKey interface{} keyfunc jwt.Keyfunc expired int tokenType string } const defaultKey = "gxt-file-server" var defaultOptions = options{ tokenType: "Bearer", expired: 7200, signingMethod: jwt.SigningMethodHS512, signingKey: []byte(defaultKey), keyfunc: func(t *jwt.Token) (interface{}, error) { if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, errors.ErrInvalidToken } return []byte(defaultKey), nil }, } type Option func(*options) type JWTAuth struct { opts *options } func New(opts ...Option) *JWTAuth { o := defaultOptions for _, opt := range opts { opt(&o) } return &JWTAuth{opts: &o} } // GenerateToken 生成令牌 func (a *JWTAuth) GenerateToken(userID string) (TokenInfo, error) { now := time.Now() expiresAt := now.Add(time.Duration(a.opts.expired) * time.Second).Unix() token := jwt.NewWithClaims(a.opts.signingMethod, &jwt.StandardClaims{ IssuedAt: now.Unix(), ExpiresAt: expiresAt, NotBefore: now.Unix(), Subject: userID, }) tokenString, err := token.SignedString(a.opts.signingKey) if err != nil { return nil, err } tokenInfo := &tokenInfo{ ExpiresAt: expiresAt, TokenType: a.opts.tokenType, AccessToken: tokenString, } return tokenInfo, nil } // 解析令牌 func (a *JWTAuth) parseToken(tokenString string) (*jwt.StandardClaims, error) { token, _ := jwt.ParseWithClaims(tokenString, &jwt.StandardClaims{}, a.opts.keyfunc) if !token.Valid { return nil, errors.ErrInvalidToken } return token.Claims.(*jwt.StandardClaims), nil } // ParseUserID 解析用户ID func (a *JWTAuth) ParseUserID(tokenString string) (string, error) { claims, err := a.parseToken(tokenString) if err != nil { return "", err } return claims.Subject, nil }