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

相关文章

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插

[分布式网络通讯框架]----Zookeeper客户端基本操作----ls、get、create、set、delete

Zookeeper数据结构 zk客户端常用命令 进入客户端 在bin目录下输入./zkCli.sh 查看根目录下数据ls / 注意:要查看哪一个节点,必须把路径写全 查看节点数据信息 get /第一行代码数据,没有的话表示没有数据 创建节点create /sl 20 /sl为节点的路径,20为节点的数据 注意,不能跨越创建,也就是说,创建sl2的时候,必须确保sl

【服务器08】之【游戏框架】之【加载主角】

首先简单了解一下帧率 FixedUpdate( )   >   Update( )   >   LateUpdate( ) 首先FixedUpdate的设置值 默认一秒运行50次 虽然默认是0.02秒,但FiexedUpdate并不是真的0.02秒调用一次,因为在脚本的生命周期内,FixedUpdate有一个小循环,这个循环也是通过物理时间累计看是不是大于0.02了,然后调用一次。有

Java中的集合框架使用技巧

Java中的集合框架使用技巧 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java中集合框架的使用技巧,这些技巧能够帮助我们更高效地处理数据和优化程序性能。 Java集合框架概述 Java集合框架提供了一组实现了各种集合接口的类和接口,用于存储和操作数据。它包括列表、集合、队列和映射等数据结构,能够满足不

[分布式网络通讯框架]----ZooKeeper下载以及Linux环境下安装与单机模式部署(附带每一步截图)

首先进入apache官网 点击中间的see all Projects->Project List菜单项进入页面 找到zookeeper,进入 在Zookeeper主页的顶部点击菜单Project->Releases,进入Zookeeper发布版本信息页面,如下图: 找到需要下载的版本 进行下载既可,这里我已经下载过3.4.10,所以以下使用3.4.10进行演示其他的步骤。

C# 日志框架Serilog使用

1、框架和说明        C#日志框架Serilog支持多种场景输出,简单验证了一下,比较方便        包的安装,推荐直接使用“推荐NuGet包管理器”安装Serilog.AspNetCore,常见的组件都已经集成在一个包中,使用比较方便 2、配置文件        Serilog可以由配置文件来定义行为,而且配置文件的修改即时生效。参考配置文件如下: {"Serilog":

Pytest和Unitest框架对比

在学到自动化的时候,很多同学都遇到了Pytest和Unitest框架,有的人是两个都学,但是学的不精只是知道分别怎么用.不了解两个区别是什么.有的是犹豫到底要学习那个框架.其实要做好自动化测试,是有必要了解不同框架之间的差异化的. Pytest 特点: Pytest采用了更简洁、更灵活的语法风格,使用“assert”语句来进行断言,Pytest可以自动发现并执行以“test_”开头的函数

mysql-mmm框架2

简介 MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM使用Perl语言开发,主要用来监控和管理MySQL Master-Master(双主)复制,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热,可以说MMM这套脚本程

MySQL-MMM框架

一、环境简述 1、工作逻辑图 2、MySQL-MMM优缺点 优点:高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证的数据的一致性。 缺点:Monitor节点是单点,可以结合Keepalived实现高可用。 3、MySQL-MMM工作原理 MMM(Master-Master replication managerfor Mys

基于LangChain框架搭建知识库

基于LangChain框架搭建知识库 说明流程1.数据加载2.数据清洗3.数据切分4.获取向量5.向量库保存到本地6.向量搜索7.汇总调用 说明 本文使用openai提供的embedding模型作为框架基础模型,知识库的搭建目的就是为了让大模型减少幻觉出现,实现起来也很简单,假如你要做一个大模型的客服问答系统,那么就把历史客服问答数据整理好,先做数据处理,在做数据向量化,最后保