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