【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

相关文章

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

Python如何自动生成环境依赖包requirements

《Python如何自动生成环境依赖包requirements》:本文主要介绍Python如何自动生成环境依赖包requirements问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录生成当前 python 环境 安装的所有依赖包1、命令2、常见问题只生成当前 项目 的所有依赖包1、

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

JSON Web Token在登陆中的使用过程

《JSONWebToken在登陆中的使用过程》:本文主要介绍JSONWebToken在登陆中的使用过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录JWT 介绍微服务架构中的 JWT 使用结合微服务网关的 JWT 验证1. 用户登录,生成 JWT2. 自定义过滤

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为