HMAC 签名
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"time"
)
type HmacUser struct {
Id string `json:"id"`
Name string `json:"name"`
Telephone string `json:"telephone"`
Password string `json:"password"`
}
type MyClaims struct {
UserId string
jwt.StandardClaims
}
var jwtKey = []byte("a_secret_key")
func main() {
r := gin.Default()
r.POST("/getToken1", func(context *gin.Context) {
var u HmacUser
context.Bind(&u)
token, err := hmacReleaseToken(u)
if err != nil {
context.JSON(http.StatusInternalServerError, err)
}
context.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "token分发成功",
"data": token,
})
})
r.POST("/checkToken1", hmacAuthMiddleware(), func(context *gin.Context) {
context.JSON(http.StatusOK, "验证成功")
})
r.Run(":9090")
}
func hmacAuthMiddleware() gin.HandlerFunc {
return func(context *gin.Context) {
auth := "fanfan"
tokenString := context.GetHeader("Authorization")
if tokenString == "" || !strings.HasPrefix(tokenString, auth+":") {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "前缀错误"})
context.Abort()
return
}
index := strings.Index(tokenString, auth+":")
tokenString = tokenString[index+len(auth)+1:]
token, claims, err := hmacParseToken(tokenString)
if err != nil || !token.Valid {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "证书无效"})
context.Abort()
return
}
var u HmacUser
context.Bind(&u)
if u.Id != claims.UserId {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "用户不存在"})
context.Abort()
return
}
context.Next()
}
}
func hmacParseToken(tokenString string) (*jwt.Token, *MyClaims, error) {
claims := &MyClaims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
return token, claims, err
}
func hmacReleaseToken(u HmacUser) (string, error) {
expirationTime := time.Now().Add(7 * 24 * time.Hour)
claims := &MyClaims{
UserId: u.Id,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
IssuedAt: time.Now().Unix(),
Issuer: "fanfan",
Subject: "user token",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
return "", err
}
return tokenString, nil
}
RSA签名
rsa签名生成公钥、私钥:https://www.metools.info/code/c80.html
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
"strings"
"time"
)
type RsaUser struct {
Id string `json:"id"`
Name string `json:"name"`
Telephone string `json:"telephone"`
Password string `json:"password"`
}
type RasClaims struct {
UserId string `json:"user_id"`
jwt.StandardClaims
}
var (
resPrivateKey []byte
resPublicKey []byte
err2_1, err2_2 error
)
func init() {
resPrivateKey, err2_1 = ioutil.ReadFile("./token/private.pem")
resPublicKey, err2_2 = ioutil.ReadFile("./token/public.pem")
if err2_1 != nil || err2_2 != nil {
panic(fmt.Sprintf("打开密钥文件错误:%s,%s", err2_1, err2_2))
}
}
func main() {
r := gin.Default()
r.POST("/getToken2", func(context *gin.Context) {
u := RsaUser{}
err := context.Bind(&u)
if err != nil {
context.JSON(http.StatusBadRequest, "参数错误")
return
}
token, err := resaReleaseToken(u)
if err != nil {
context.JSON(http.StatusBadRequest, "生成token错误")
return
}
context.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "token分发成功",
"data": token,
})
})
r.POST("/checkToken2", rsaTokenMiddle(), func(context *gin.Context) {
context.JSON(http.StatusOK, "验证成功")
})
r.Run(":9090")
}
func rsaTokenMiddle() gin.HandlerFunc {
return func(context *gin.Context) {
auth := "fanfan"
tokenString := context.GetHeader("Authorization")
if tokenString == "" || !strings.HasPrefix(tokenString, auth+":") {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "无效的token"})
context.Abort()
return
}
index := strings.Index(tokenString, auth+":")
tokenString = tokenString[index+len(auth)+1:]
claims, err := rsaJwtTokenRead(tokenString)
if err != nil {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "证书无效"})
context.Abort()
return
}
claimsValue := claims.(jwt.MapClaims)
if claimsValue["user_id"] == nil {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "用户不存在"})
context.Abort()
return
}
var u RsaUser
context.Bind(&u)
if u.Id != claimsValue["user_id"].(string) {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "用户不存在"})
context.Abort()
return
}
context.Next()
}
}
func rsaJwtTokenRead(tokenString string) (interface{}, error) {
pem, err := jwt.ParseRSAPublicKeyFromPEM(resPublicKey)
if err != nil {
return nil, err
}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, OK := token.Method.(*jwt.SigningMethodRSA); !OK {
return nil, fmt.Errorf("解析方法错误")
}
return pem, err
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, err
}
return nil, err
}
func resaReleaseToken(u RsaUser) (interface{}, error) {
tokenGen, err := rasJwtTokenGen(u.Id)
return tokenGen, err
}
func rasJwtTokenGen(id string) (interface{}, error) {
private, err := jwt.ParseRSAPrivateKeyFromPEM(resPrivateKey)
if err != nil {
return nil, err
}
claims := &RasClaims{
UserId: id,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(7 * 24 * time.Hour).Unix(),
Issuer: "fanfan",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
signedString, err := token.SignedString(private)
return signedString, err
}
ECDSA签名
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"errors"
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"time"
)
type EcdsaUser struct {
Id string `json:"id"`
Name string `json:"name"`
Telephone string `json:"telephone"`
Password string `json:"password"`
}
type EcdsaClaims struct {
UserId string `json:"user_id"`
jwt.StandardClaims
}
var (
err3 error
eccPrivateKey *ecdsa.PrivateKey
eccPublicKey *ecdsa.PublicKey
)
func init() {
eccPrivateKey, eccPublicKey, err3 = getEcdsaKey(2)
if err3 != nil {
panic(err3)
return
}
}
func ecdsaReleaseToken(u EcdsaUser) (interface{}, error) {
claims := &EcdsaClaims{
UserId: u.Id,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(7 * 24 * time.Hour).Unix(),
Issuer: "fanfan",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
signedString, err := token.SignedString(eccPrivateKey)
return signedString, err
}
func main() {
r := gin.Default()
r.POST("/getToken3", func(context *gin.Context) {
var u EcdsaUser
err := context.Bind(&u)
if err != nil {
context.JSON(http.StatusInternalServerError, "参数错误")
}
token, err := ecdsaReleaseToken(u)
if err != nil {
context.JSON(http.StatusInternalServerError, err)
}
context.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "token分发成功",
"data": token,
})
})
r.POST("/checkToken3", ecdsaTokenMiddleware(), func(context *gin.Context) {
context.JSON(http.StatusOK, "验证成功")
})
r.Run(":9090")
}
func ecdsaTokenMiddleware() gin.HandlerFunc {
return func(context *gin.Context) {
auth := "fanfan"
tokenString := context.GetHeader("Authorization")
if tokenString == "" || !strings.HasPrefix(tokenString, auth+":") {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "无效的token"})
context.Abort()
return
}
index := strings.Index(tokenString, auth+":")
tokenString = tokenString[index+len(auth)+1:]
claims, err := ecdsaJwtTokenRead(tokenString)
if err != nil {
context.AbortWithStatusJSON(http.StatusUnauthorized, err)
return
}
claimsValue := claims.(jwt.MapClaims)
if claimsValue["user_id"] == nil {
context.AbortWithStatusJSON(http.StatusUnauthorized, "id不存在")
return
}
var u EcdsaUser
context.Bind(&u)
if u.Id != claimsValue["user_id"] {
context.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "用户不存在"})
context.Abort()
return
}
context.Next()
}
}
func ecdsaJwtTokenRead(tokenString string) (interface{}, error) {
myToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok {
return nil, fmt.Errorf("无效的签名方法")
}
return eccPublicKey, nil
})
if claims, ok := myToken.Claims.(jwt.MapClaims); ok && myToken.Valid {
return claims, nil
}
return nil, err
}
func getEcdsaKey(keyType int) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) {
var err error
var prk *ecdsa.PrivateKey
var pub *ecdsa.PublicKey
var curve elliptic.Curve
switch keyType {
case 1:
curve = elliptic.P224()
case 2:
curve = elliptic.P256()
case 3:
curve = elliptic.P384()
case 4:
curve = elliptic.P521()
default:
err = errors.New("输入签名 key 类型错误!")
return nil, nil, err
}
prk, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, nil, err
}
pub = &prk.PublicKey
return prk, pub, err
}