parent
a203ac5387
commit
d048ce9e2a
7 changed files with 276 additions and 0 deletions
@ -0,0 +1,70 @@ |
||||
package jwts |
||||
|
||||
import ( |
||||
"crypto/ecdsa" |
||||
"crypto/elliptic" |
||||
"fmt" |
||||
"github.com/dgrijalva/jwt-go" |
||||
"github.com/pkg/errors" |
||||
"math/big" |
||||
) |
||||
|
||||
var ( |
||||
//ES256 keys
|
||||
ECDSAKeyD = "7A429E82FF619D38CC8071111988FFA75625DD83B22E9EBEC29F17BFA7BF3A03" |
||||
ECDSAKeyX = "76E93569AB21A614BCD581858D0066C8ED611DEFEEA2821CC43EC9E08948A151" |
||||
ECDSAKeyY = "61BB8B7EF5333E2E87CDE6DF522BE6BF253C637768F9FA8D9EDCAB270E09B43C" |
||||
) |
||||
|
||||
// 获取token数据
|
||||
func JWTGetMapString(map1 jwt.Claims) (string, error) { |
||||
|
||||
keyD := new(big.Int) |
||||
keyX := new(big.Int) |
||||
keyY := new(big.Int) |
||||
keyD.SetString(ECDSAKeyD, 16) |
||||
keyX.SetString(ECDSAKeyX, 16) |
||||
keyY.SetString(ECDSAKeyY, 16) |
||||
|
||||
publicKey := ecdsa.PublicKey{ |
||||
Curve: elliptic.P256(), |
||||
X: keyX, |
||||
Y: keyY, |
||||
} |
||||
privateKey := ecdsa.PrivateKey{D: keyD, PublicKey: publicKey} |
||||
|
||||
tokenJwt := jwt.NewWithClaims(jwt.SigningMethodES256, map1) |
||||
|
||||
if tokenString, err := tokenJwt.SignedString(&privateKey); err != nil { |
||||
return "", err |
||||
} else { |
||||
return tokenString, nil |
||||
} |
||||
} |
||||
|
||||
// 解析jwt数据
|
||||
func JWTGetStringMap(jwtString string) (map[string]interface{}, error) { |
||||
keyX := new(big.Int) |
||||
keyY := new(big.Int) |
||||
|
||||
keyX.SetString(ECDSAKeyX, 16) |
||||
keyY.SetString(ECDSAKeyY, 16) |
||||
publickKey := ecdsa.PublicKey{ |
||||
Curve: elliptic.P256(), |
||||
X: keyX, |
||||
Y: keyY, |
||||
} |
||||
jwtToken, err := jwt.Parse(jwtString, func(token *jwt.Token) (interface{}, error) { |
||||
if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok { |
||||
return nil, errors.New(fmt.Sprintf("json 解析失败:%+v", token)) |
||||
} |
||||
return &publickKey, nil |
||||
}) |
||||
|
||||
if err == nil { |
||||
if claims, ok := jwtToken.Claims.(jwt.MapClaims); ok { |
||||
return claims, nil |
||||
} |
||||
} |
||||
return nil, errors.New(fmt.Sprintf("json 解析失败:%v", jwtString)) |
||||
} |
@ -0,0 +1,104 @@ |
||||
package xaes |
||||
|
||||
import ( |
||||
"bytes" |
||||
"crypto/aes" |
||||
"crypto/cipher" |
||||
) |
||||
|
||||
//#;AES加解密使用 长度 16, 24, 32
|
||||
//const aesKey = "sfe023f_9fd&fwfl"
|
||||
|
||||
////加密字符串
|
||||
//func AesEncrypt(hstring string) (string, error) {
|
||||
// if result, err := aesEncrypt([]byte(hstring), []byte(aesKey)); err != nil {
|
||||
// return "", err
|
||||
// } else {
|
||||
// return base64.StdEncoding.EncodeToString(result), nil
|
||||
// }
|
||||
//}
|
||||
//
|
||||
////解密字符串
|
||||
//func AesDecrypt(hstring string) (string, error) {
|
||||
// if bye, err := base64.StdEncoding.DecodeString(hstring); err != nil {
|
||||
// return "", err
|
||||
// } else {
|
||||
// if result, err := aesDecrypt(bye, []byte(aesKey)); err != nil {
|
||||
// return "", err
|
||||
// } else {
|
||||
// return string(result), nil
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//func AESTestCode() {
|
||||
// // AES-128。key长度:16, 24, 32 bytes 对应 AES-128, AES-192, AES-256
|
||||
// key := []byte("sfe023f_9fd&fwfl")
|
||||
// result, err := aesEncrypt([]byte("polaris@studygolang"), key)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// fmt.Println(result)
|
||||
// a, _ := AesEncrypt("polaris@studygolang")
|
||||
// aa, _ := base64.StdEncoding.DecodeString(a)
|
||||
// origData, err := aesDecrypt(aa, key)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// fmt.Println(string(origData))
|
||||
//}
|
||||
|
||||
func Encrypt(origData, key []byte) ([]byte, error) { |
||||
block, err := aes.NewCipher(key) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
blockSize := block.BlockSize() |
||||
origData = pKCS5Padding(origData, blockSize) |
||||
// origData = ZeroPadding(origData, block.BlockSize())
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) |
||||
crypted := make([]byte, len(origData)) |
||||
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
|
||||
// crypted := origData
|
||||
blockMode.CryptBlocks(crypted, origData) |
||||
return crypted, nil |
||||
} |
||||
|
||||
func Decrypt(crypted, key []byte) ([]byte, error) { |
||||
block, err := aes.NewCipher(key) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
blockSize := block.BlockSize() |
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) |
||||
origData := make([]byte, len(crypted)) |
||||
// origData := crypted
|
||||
|
||||
blockMode.CryptBlocks(origData, crypted) |
||||
|
||||
origData = pKCS5UnPadding(origData) |
||||
// origData = ZeroUnPadding(origData)
|
||||
return origData, nil |
||||
} |
||||
|
||||
// func zeroPadding(ciphertext []byte, blockSize int) []byte {
|
||||
// padding := blockSize - len(ciphertext)%blockSize
|
||||
// padtext := bytes.Repeat([]byte{0}, padding)
|
||||
// return append(ciphertext, padtext...)
|
||||
// }
|
||||
//
|
||||
// func zeroUnPadding(origData []byte) []byte {
|
||||
// length := len(origData)
|
||||
// unpadding := int(origData[length-1])
|
||||
// return origData[:(length - unpadding)]
|
||||
// }
|
||||
func pKCS5Padding(ciphertext []byte, blockSize int) []byte { |
||||
padding := blockSize - len(ciphertext)%blockSize |
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding) |
||||
return append(ciphertext, padtext...) |
||||
} |
||||
|
||||
func pKCS5UnPadding(origData []byte) []byte { |
||||
length := len(origData) |
||||
unpadding := int(origData[length-1]) |
||||
return origData[:(length - unpadding)] |
||||
} |
@ -0,0 +1,14 @@ |
||||
package xbase64 |
||||
|
||||
import ( |
||||
b64 "encoding/base64" |
||||
) |
||||
|
||||
func Encode(s string) string { |
||||
return b64.StdEncoding.EncodeToString([]byte(s)) |
||||
} |
||||
|
||||
func Decode(s string) (string, error) { |
||||
ds, err := b64.StdEncoding.DecodeString(s) |
||||
return string(ds), err |
||||
} |
@ -0,0 +1,85 @@ |
||||
package xtoken |
||||
|
||||
import ( |
||||
"context" |
||||
"encoding/json" |
||||
"errors" |
||||
"git.diulo.com/mogfee/protoc-gen-kit/pkg/jwts" |
||||
"git.diulo.com/mogfee/protoc-gen-kit/pkg/xaes" |
||||
"git.diulo.com/mogfee/protoc-gen-kit/pkg/xbase64" |
||||
"github.com/dgrijalva/jwt-go" |
||||
"time" |
||||
) |
||||
|
||||
const ( |
||||
// expiredTime 授权结束时间
|
||||
expiredTime = 7200 |
||||
|
||||
tokenKey = "68Tz&xWUW5U$Id45" |
||||
) |
||||
|
||||
type TokenInfo struct { |
||||
Id int64 |
||||
Permission []string |
||||
} |
||||
|
||||
var tokenExpired = errors.New("token expired") |
||||
|
||||
type tokenStoreInfo struct { |
||||
Created int64 `json:"created"` |
||||
ExpiredAt int64 `json:"expired_at"` |
||||
Id int64 `json:"id"` |
||||
Permission []string `json:"permission"` |
||||
} |
||||
|
||||
func GetTokenStr(ctx context.Context, info TokenInfo) (string, error) { |
||||
ctime := time.Now().Unix() |
||||
|
||||
tokenString, err := jwts.JWTGetMapString(jwt.MapClaims{ |
||||
"id": info.Id, |
||||
"permission": info.Permission, |
||||
"created": ctime, |
||||
"expired_at": ctime + expiredTime, |
||||
}) |
||||
|
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
aesString, err := xaes.Encrypt([]byte(tokenString), []byte(tokenKey)) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
return xbase64.Encode(string(aesString)), nil |
||||
} |
||||
|
||||
func ParseToken(tokenStr string) (*TokenInfo, error) { |
||||
tokenStr, err := xbase64.Decode(tokenStr) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
body, err := xaes.Decrypt([]byte(tokenStr), []byte(tokenKey)) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
mps, err := jwts.JWTGetStringMap(string(body)) |
||||
if err != nil { |
||||
return nil, errors.New("token parse error") |
||||
} |
||||
b, _ := json.Marshal(mps) |
||||
row := tokenStoreInfo{} |
||||
if err = json.Unmarshal(b, &row); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
if row.ExpiredAt < time.Now().Unix() || row.Id <= 0 { |
||||
return nil, tokenExpired |
||||
} |
||||
|
||||
return &TokenInfo{ |
||||
Id: row.Id, |
||||
Permission: row.Permission, |
||||
}, nil |
||||
} |
||||
func IsExpired(err error) bool { |
||||
return err == tokenExpired |
||||
} |
Loading…
Reference in new issue