本文主要是介绍gin框架精通篇(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
HMAC 签名
package mainimport ("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 stringjwt.StandardClaims
}var jwtKey = []byte("a_secret_key")func main() {r := gin.Default()r.POST("/getToken1", func(context *gin.Context) {var u HmacUsercontext.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 HmacUsercontext.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 mainimport ("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 []byteresPublicKey []byteerr2_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 RsaUsercontext.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 mainimport ("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 erroreccPrivateKey *ecdsa.PrivateKeyeccPublicKey *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 EcdsaUsererr := 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 EcdsaUsercontext.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 errorvar prk *ecdsa.PrivateKeyvar pub *ecdsa.PublicKeyvar curve elliptic.Curveswitch 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.PublicKeyreturn prk, pub, err
}
这篇关于gin框架精通篇(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!