package auth import ( "encoding/json" "github.com/dgrijalva/jwt-go" "gxt-api-frame/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 = "smartpark" 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 }, } // SetSigningMethod 设定签名方式 func SetSigningMethod(method jwt.SigningMethod) Option { return func(o *options) { o.signingMethod = method } } // SetSigningKey 设定签名key func SetSigningKey(key interface{}) Option { return func(o *options) { o.signingKey = key } } // SetKeyfunc 设定验证key的回调函数 func SetKeyfunc(keyFunc jwt.Keyfunc) Option { return func(o *options) { o.keyfunc = keyFunc } } // SetExpired 设定令牌过期时长(单位秒,默认7200) func SetExpired(expired int) Option { return func(o *options) { o.expired = expired } } 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 } // Auther 认证接口 type Auther interface { // GenerateToken 生成令牌 GenerateToken(userID string) (TokenInfo, error) // 销毁令牌 //DestroyToken(accessToken string) error // ParseUserID 解析用户ID ParseUserID(accessToken string) (string, error) // 释放资源 //Release() error //GenerateApiToken(userID string) (TokenInfo, error) }