【REST2SQL】12 REST2SQL增加Token生成和验证

2024-03-09 20:36

本文主要是介绍【REST2SQL】12 REST2SQL增加Token生成和验证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【REST2SQL】01RDB关系型数据库REST初设计
【REST2SQL】02 GO连接Oracle数据库
【REST2SQL】03 GO读取JSON文件
【REST2SQL】04 REST2SQL第一版Oracle版实现
【REST2SQL】05 GO 操作 达梦 数据库
【REST2SQL】06 GO 跨包接口重构代码
【REST2SQL】07 GO 操作 Mysql 数据库
【REST2SQL】08 日志重构增加输出到文件log.txt
【REST2SQL】09 给Go的可执行文件exe加图标和版本信息等
【REST2SQL】10 REST2SQL操作指南
【REST2SQL】11 基于jwt-go生成token与验证


【REST2SQL】11 基于jwt-go生成token与验证的Token生成和验证合并到【REST2SQL】

1 Rest2sql目录下新建token子目录

  • Rest2sql目录下新建token子目录
  • 拷贝 【REST2SQL】11 基于jwt-go生成token与验证 的mytoken.go
  • mytoken.go改名为 token.go
    在这里插入图片描述

2 token.go的代码重构

  • 包名改为token
  • 屏蔽或删除 main()入口函数
  • 重构全局变量,都改为外部不可见,即变量名改为首字母改为小写即可
  • 只暴露生成token函数GenerateTokenHandler()和验证token函数ValidateTokenHandler()
  • 暴露函数第二个参数重构

重构完成的代码如下:

package tokenimport ("crypto/rand""encoding/json""fmt""log""net/http""time"jwt "github.com/dgrijalva/jwt-go"
)// 初始化函数
func init() {// 实例化计数计时器counter = NewCounter()// 初始化随机 Keykey, err := generateRandomString(16)if err != nil {log.Fatal(err)}// 打印时间戳fmt.Println("Start At timeStamp :", timeStamp, time.Unix(timeStamp, 0), key)
}// Counter 定义一个简单的计数器
type Counter struct {value      inttimeStampc int64 // 时间戳,用于定期更新密钥key
}// 计时器变量实例
var counter *Counter// NewCounter 创建一个新的计数器
func NewCounter() *Counter {return &Counter{value: 0, timeStampc: time.Now().Unix()}
}// Increment 增加计数器的值
func (c *Counter) Increment() {c.value++c.timeStampc = time.Now().Unix()
}// // Decrement 减少计数器的值
// func (c *Counter) Decrement() {
// 	c.value--
// }// // Reset 重置计数器的值为0
// func (c *Counter) Reset() {
// 	c.value = 0
// }// GetValue 返回计数器的当前值
func (c *Counter) GetCounter() *Counter {return c
}// 
// 定义Token的Claims
type customClaims struct {Userid string `json:"userid"`Passwd string `json:"passwd"`jwt.StandardClaims
}// 定义Token相关变量
var (uid string = "BLMa"  //用户名pwd string = "5217"  //密码key string = "token" //默认密钥,服务启动时会修改iss string = "guwuy" //签发者timeStamp   int64         = time.Now().Unix() // 时间戳,用于定期更新密钥keytimeSecond  int64         = 20                //60 * 60 * 24 * 7  //一周时间的秒数,用于7天修改一次KeytimeExpires time.Duration = 60 * 60 * 8       // Token 过期时间 秒数,8小时
)// generateRandomString 生成一个指定长度的随机字符串
func generateRandomString(length int) (string, error) {const letters = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"bytes := make([]byte, length)if _, err := rand.Read(bytes); err != nil {return "", err}for i, b := range bytes {bytes[i] = letters[b%byte(len(letters))]}return string(bytes), nil
}// 定期生成随机Key
func generateRandomKey() {//当前时间戳timestamp := counter.GetCounter().timeStampc//fmt.Println("Now timeStamp,timestamp:", timeStamp, timestamp)if timestamp-timeStamp > timeSecond {counter.Increment()// 修改Keykey, err := generateRandomString(16)if err != nil {log.Fatal(err)}timeStamp = timestamp // 更新Key修改的时间戳// 打印时间戳fmt.Println("Now timeStamp :", timeStamp, time.Unix(timeStamp, 0), key)}
}// 生成新的Token
func generateToken(userId string) (string, error) {// 计数器,计时器counter.Increment()// 设置Claimsclaims := customClaims{Userid: userId,Passwd: pwd,StandardClaims: jwt.StandardClaims{ExpiresAt: time.Now().Add(time.Second * timeExpires).Unix(), // 设置过期时间Issuer:    iss,                                              // 设置签发者},}// 创建Tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)// 定期生成随机KeygenerateRandomKey()// 签名Token,这里使用硬编码的密钥,实际生产环境中应使用更安全的密钥管理方式signedToken, err := token.SignedString([]byte(key))if err != nil {return "", err}return signedToken, nil
}// 验证Token
func validateToken(tokenString string) (*customClaims, error) {// 解析Tokentoken, err := jwt.ParseWithClaims(tokenString, &customClaims{}, func(token *jwt.Token) (interface{}, error) {// 验证Token的签名,这里使用硬编码的密钥return []byte(key), nil})if claims, ok := token.Claims.(*customClaims); ok && token.Valid {return claims, nil}return nil, err
}// HTTP处理函数:生成Token
func GenerateTokenHandler(w http.ResponseWriter, uid_pwd map[string]string) {//请求参数,实际情况下,这里可能从请求参数或身份验证过程中获取uid = uid_pwd["Userid"]pwd = uid_pwd["Passwd"]// 这里加uid,pwd的数据库校验//fmt.Println(uid, pwd)token, err := generateToken(uid)if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(map[string]string{"token": token,})
}// HTTP处理函数:验证Token
func ValidateTokenHandler(w http.ResponseWriter, tokenString string) {claims, err := validateToken(tokenString)if err != nil {http.Error(w, err.Error(), http.StatusUnauthorized)return}w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(map[string]interface{}{"userid":  claims.Userid,"expires": claims.ExpiresAt,})
}// // main入口
// func main() {
// 	// 检查并生成Key
// 	GenerateRandomKey()// 	// Token 路由
// 	http.HandleFunc("/generate-token", generateTokenHandler)
// 	// Http://localhost:8080/generate-token?userid=blma&passwd=5217
// 	// curl Http://localhost:8080/generate-token?userid=blma%26passwd=5217
// 	http.HandleFunc("/validate-token", validateTokenHandler)
// 	//curl http://localhost:8080/validate-token -H "Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiI5OTk4IiwicGFzc3dkIjoiODk5OSIsImV4cCI6MTcwOTcyMDU0MSwiaXNzIjoiZ3V3dXkifQ.UXiW-cgnDZfGUmLtv_yme6gzFZ9XDiKaNATIdFzJ2fY"// 	fmt.Println("Starting Token server ...")
// 	fmt.Println("Http://localhost:8080/generate-token?userid=&passwd=")
// 	fmt.Println("curl http://localhost:8080/validate-token -H \"Authorization:token\"")
// 	log.Fatal(http.ListenAndServe(":8080", nil))
// }

3 rest2sql.go的 handler() 增加token访问路由

重构的核心代码如下:

  • 请求路径错误提示代码:
// 2请求路径Pathreq["Path"] = r.URL.Pathpath := strings.Split(r.URL.Path, "/")if len(path) < 3 {w.Write([]byte("400 Bad Request错误请求。请尝试/rest/xxx or /sql/xxx or /TOKEN/xxx"))return}
  • 允许的请求路径代码:
// 3 请求类型REST or SQL or Tokenrors := strings.ToUpper(fmt.Sprint(path[1]))// 支持的请求类型if !(rors == "REST" || rors == "SQL" || rors == "TOKEN") {w.Write([]byte("400 Bad Request错误请求。请尝试/REST/xxx or /SQL/xxx or /TOKEN/xxx"))return}
  • 请求头token结构代码:
// 8 请求头 Authorizationreq["Authorization"] = r.Header.Get("Authorization") // 假设Token在Authorization头中
  • 请求参数增加userid和passw代码:
// 9 请求参数query := r.URL.Query()req["Userid"] = query.Get("userid") // 登录用户req["Passwd"] = query.Get("passwd") // 登录密码

3 dothing.go代码重构

分支代码:
case "TOKEN":// Token 生成与校验doTOKEN(w, req)
  • doTiken函数代码:
// 根据请求参数执行不同的TOKEN操作 ///
func doTOKEN(w http.ResponseWriter, req map[string]interface{}) {// token操作, generate or validateresToken := strings.ToLower(req["ResName"].(string))switch resToken {case "generate-token":// w.Write([]byte("generate-token"))var uid_pwd map[string]string = make(map[string]string)uid_pwd["Userid"] = req["Userid"].(string)uid_pwd["Passwd"] = req["Passwd"].(string)token.GenerateTokenHandler(w, uid_pwd)// http://127.0.0.1:5217/TOKEN/generate-token?userid=9998&passwd=8999case "validate-token"://w.Write([]byte("validate-token"))var tokenString string = req["Authorization"].(string)token.ValidateTokenHandler(w, tokenString)// curl http://localhost:5217/token/validate-token -H "Authorization:token"}
}

4 实操演练

Setp 1 启动服务

在这里插入图片描述

Step 2 生成Token

http://127.0.0.1:5217/TOKEN/generate-token?userid=9998&passwd=8999

在这里插入图片描述

Step 3 验证Token

curl http://localhost:5217/token/validate-token -H "Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDk4Njk0OTEsImlzcyI6Imd1d3V5In0.7CLaQKNXZOhnirLfOb_1meYYnc6KVDkXUhrxbfvYgKw"

在这里插入图片描述

Step 4 服务日志

在这里插入图片描述


本文完。

这篇关于【REST2SQL】12 REST2SQL增加Token生成和验证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Python使用python-pptx自动化操作和生成PPT

《Python使用python-pptx自动化操作和生成PPT》这篇文章主要为大家详细介绍了如何使用python-pptx库实现PPT自动化,并提供实用的代码示例和应用场景,感兴趣的小伙伴可以跟随小编... 目录使用python-pptx操作PPT文档安装python-pptx基础概念创建新的PPT文档查看

在ASP.NET项目中如何使用C#生成二维码

《在ASP.NET项目中如何使用C#生成二维码》二维码(QRCode)已广泛应用于网址分享,支付链接等场景,本文将以ASP.NET为示例,演示如何实现输入文本/URL,生成二维码,在线显示与下载的完整... 目录创建前端页面(Index.cshtml)后端二维码生成逻辑(Index.cshtml.cs)总结

Python实现数据可视化图表生成(适合新手入门)

《Python实现数据可视化图表生成(适合新手入门)》在数据科学和数据分析的新时代,高效、直观的数据可视化工具显得尤为重要,下面:本文主要介绍Python实现数据可视化图表生成的相关资料,文中通过... 目录前言为什么需要数据可视化准备工作基本图表绘制折线图柱状图散点图使用Seaborn创建高级图表箱线图热

SQLServer中生成雪花ID(Snowflake ID)的实现方法

《SQLServer中生成雪花ID(SnowflakeID)的实现方法》:本文主要介绍在SQLServer中生成雪花ID(SnowflakeID)的实现方法,文中通过示例代码介绍的非常详细,... 目录前言认识雪花ID雪花ID的核心特点雪花ID的结构(64位)雪花ID的优势雪花ID的局限性雪花ID的应用场景

Django HTTPResponse响应体中返回openpyxl生成的文件过程

《DjangoHTTPResponse响应体中返回openpyxl生成的文件过程》Django返回文件流时需通过Content-Disposition头指定编码后的文件名,使用openpyxl的sa... 目录Django返回文件流时使用指定文件名Django HTTPResponse响应体中返回openp

MySQL 主从复制部署及验证(示例详解)

《MySQL主从复制部署及验证(示例详解)》本文介绍MySQL主从复制部署步骤及学校管理数据库创建脚本,包含表结构设计、示例数据插入和查询语句,用于验证主从同步功能,感兴趣的朋友一起看看吧... 目录mysql 主从复制部署指南部署步骤1.环境准备2. 主服务器配置3. 创建复制用户4. 获取主服务器状态5

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法