gin框架精通篇(三)

2024-05-28 05:04
文章标签 精通 框架 gin

本文主要是介绍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框架精通篇(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1009610

相关文章

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

史上最全MybatisPlus从入门到精通

《史上最全MybatisPlus从入门到精通》MyBatis-Plus是MyBatis增强工具,简化开发并提升效率,支持自动映射表名/字段与实体类,提供条件构造器、多种查询方式(等值/范围/模糊/分页... 目录1.简介2.基础篇2.1.通用mapper接口操作2.2.通用service接口操作3.进阶篇3

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二