first commit
This commit is contained in:
		
							
								
								
									
										20
									
								
								pkg/token/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								pkg/token/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
## 与 UrlSign 对应的 PHP 加密算法
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
// 对 params key 进行排序
 | 
			
		||||
ksort($params);
 | 
			
		||||
 | 
			
		||||
// 对 sortParams 进行 Encode
 | 
			
		||||
$sortParamsEncode = http_build_query($params);
 | 
			
		||||
 | 
			
		||||
// 加密字符串规则 path + method + sortParamsEncode + secret
 | 
			
		||||
$encryptStr = $path . $method . $sortParamsEncode . $secret
 | 
			
		||||
 | 
			
		||||
// 对加密字符串进行 md5
 | 
			
		||||
$md5Str = md5($encryptStr);
 | 
			
		||||
 | 
			
		||||
// 对 md5Str 进行 base64 encode
 | 
			
		||||
$tokenString = base64_encode($md5Str);
 | 
			
		||||
 | 
			
		||||
echo $tokenString;
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										36
									
								
								pkg/token/token.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								pkg/token/token.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
package token
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang-jwt/jwt/v4"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ Token = (*token)(nil)
 | 
			
		||||
 | 
			
		||||
type Token interface {
 | 
			
		||||
	// i 为了避免被其他包实现
 | 
			
		||||
	i()
 | 
			
		||||
 | 
			
		||||
	// JwtSign JWT 签名方式
 | 
			
		||||
	JwtSign(userId, subject string, expireDuration time.Duration) (tokenString string, err error)
 | 
			
		||||
	JwtParse(tokenString string) (*jwt.RegisteredClaims, error)
 | 
			
		||||
 | 
			
		||||
	// UrlSign URL 签名方式,不支持解密
 | 
			
		||||
	UrlSign(path string, method string, params url.Values) (tokenString string, err error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type token struct {
 | 
			
		||||
	secret string
 | 
			
		||||
	domain []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New(secret string, domain ...string) Token {
 | 
			
		||||
	return &token{
 | 
			
		||||
		secret: secret,
 | 
			
		||||
		domain: domain,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *token) i() {}
 | 
			
		||||
							
								
								
									
										43
									
								
								pkg/token/token_jwt.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/token/token_jwt.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
package token
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/golang-jwt/jwt/v4"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (t *token) JwtSign(userId, subject string, expireDuration time.Duration) (tokenString string, err error) {
 | 
			
		||||
	// The token content.
 | 
			
		||||
	// iss: (Issuer)签发者
 | 
			
		||||
	// iat: (Issued At)签发时间,用Unix时间戳表示
 | 
			
		||||
	// exp: (Expiration Time)过期时间,用Unix时间戳表示
 | 
			
		||||
	// aud: (Audience)接收该JWT的一方
 | 
			
		||||
	// sub: (Subject)该JWT的主题
 | 
			
		||||
	// nbf: (Not Before)不要早于这个时间
 | 
			
		||||
	// jti: (JWT ID)用于标识JWT的唯一ID
 | 
			
		||||
	c := &jwt.RegisteredClaims{
 | 
			
		||||
		Issuer:    "BvBeJ",
 | 
			
		||||
		Subject:   subject,
 | 
			
		||||
		Audience:  jwt.ClaimStrings(t.domain),
 | 
			
		||||
		ExpiresAt: jwt.NewNumericDate(time.Now().Add(expireDuration)),
 | 
			
		||||
		NotBefore: jwt.NewNumericDate(time.Now()),
 | 
			
		||||
		IssuedAt:  jwt.NewNumericDate(time.Now()),
 | 
			
		||||
		ID:        userId,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tokenString, err = jwt.NewWithClaims(jwt.SigningMethodHS256, c).SignedString([]byte(t.secret))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *token) JwtParse(tokenString string) (*jwt.RegisteredClaims, error) {
 | 
			
		||||
	tokenClaims, err := jwt.ParseWithClaims(tokenString, &jwt.RegisteredClaims{}, func(token *jwt.Token) (any, error) {
 | 
			
		||||
		return []byte(t.secret), nil
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if tokenClaims != nil {
 | 
			
		||||
		if c, ok := tokenClaims.Claims.(*jwt.RegisteredClaims); ok && tokenClaims.Valid {
 | 
			
		||||
			return c, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								pkg/token/token_url.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								pkg/token/token_url.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
package token
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// UrlSign
 | 
			
		||||
// path 请求的路径 (不附带 querystring)
 | 
			
		||||
func (t *token) UrlSign(path string, method string, params url.Values) (tokenString string, err error) {
 | 
			
		||||
	// 合法的 Methods
 | 
			
		||||
	methods := map[string]bool{
 | 
			
		||||
		"get":     true,
 | 
			
		||||
		"post":    true,
 | 
			
		||||
		"put":     true,
 | 
			
		||||
		"path":    true,
 | 
			
		||||
		"delete":  true,
 | 
			
		||||
		"head":    true,
 | 
			
		||||
		"options": true,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	methodName := strings.ToLower(method)
 | 
			
		||||
	if !methods[methodName] {
 | 
			
		||||
		err = errors.New("method param error")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Encode() 方法中自带 sorted by key
 | 
			
		||||
	sortParamsEncode := params.Encode()
 | 
			
		||||
 | 
			
		||||
	// 加密字符串规则 path + method + sortParamsEncode + secret
 | 
			
		||||
	encryptStr := fmt.Sprintf("%s%s%s%s", path, methodName, sortParamsEncode, t.secret)
 | 
			
		||||
 | 
			
		||||
	// 对加密字符串进行 md5
 | 
			
		||||
	s := md5.New()
 | 
			
		||||
	s.Write([]byte(encryptStr))
 | 
			
		||||
	md5Str := hex.EncodeToString(s.Sum(nil))
 | 
			
		||||
 | 
			
		||||
	// 对 md5Str 进行 base64 encode
 | 
			
		||||
	tokenString = base64.StdEncoding.EncodeToString([]byte(md5Str))
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user