Go基础(Gin)

go mod init my-gin-app 初始化一个 Go 项目,创建一个go.mod文件

go mod tidy                   自动整理项目依赖,确保go.modgo.sum文件与代码实际使用的依赖一致

  • go mod init:创建项目的 “依赖说明书”。
  • go mod tidy:整理 “说明书”,让依赖清单精确匹配代码。

代码基础

package mainimport "github.com/gin-gonic/gin"func main() {// 创建默认引擎,包含日志和恢复中间件r := gin.Default()// 定义根路径的 GET 请求r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Hello World",})})// 启动服务器,监听 8080 端口r.Run() // 默认监听 :8080
}

参数查询代码

package mainimport "github.com/gin-gonic/gin"func main() {// 创建默认引擎,包含日志和恢复中间件r := gin.Default()// 处理带参数的 URL:/users/123r.GET("/users/:id", func(c *gin.Context) {id := c.Param("id")c.JSON(200, gin.H{"user_id": id,})})// 启动服务器,监听 8080 端口r.Run() // 默认监听 :8080
}

处理 POST 请求并验证账号密码

package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()// 处理 POST 请求,验证账号密码r.POST("/login", func(c *gin.Context) {// 定义请求体结构type LoginRequest struct {Username string `json:"username" binding:"required"`Password string `json:"password" binding:"required"`}var req LoginRequest// 绑定 JSON 请求体并验证if err := c.ShouldBindJSON(&req); err != nil {c.JSON(400, gin.H{"error": err.Error()})return}// 验证账号密码if req.Username == "123" && req.Password == "123" {c.JSON(200, gin.H{"message": "验证正确"})} else {c.JSON(401, gin.H{"message": "账号或密码错误"})}})r.Run()
}
  • json:"password" 就是这个「翻译器」。
  • 当你收到一个 JSON 数据(比如 {"password": "123"}),Gin 会自动把 JSON 里的 password 字段,对应到 Go 代码里的 Password 变量。
  • binding:"required" 表示这个字段「必须存在」,如果 JSON 里没有这个字段,就会报错。

ShouldBindJSON 会做两件事

  1. 翻译:把 JSON 里的字段名(比如 password),对应到 Go 结构体的变量(比如 Password)。
  2. 检查规则:检查每个字段是否符合 binding:"required" 等规则。

JWT

package mainimport ("github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin""net/http""time"
)// 密钥(生产环境应从配置文件或环境变量获取)
var jwtKey = []byte("your-secret-key")// Token中包含的用户信息
type Claims struct {Username string `json:"username"`jwt.StandardClaims
}// 生成JWT Token
func generateToken(username string) (string, error) {expirationTime := time.Now().Add(1 * time.Hour)claims := &Claims{Username: username,StandardClaims: jwt.StandardClaims{ExpiresAt: expirationTime.Unix(),IssuedAt:  time.Now().Unix(),Issuer:    "your-app",},}token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)return token.SignedString(jwtKey)
}// 验证JWT Token
func validateToken(tokenStr string) (*Claims, error) {claims := &Claims{}token, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil})if err != nil || !token.Valid {return nil, err}return claims, nil
}// 登录接口 - 验证用户并生成Token
func loginHandler(c *gin.Context) {type LoginRequest struct {Username string `json:"username" binding:"required"`Password string `json:"password" binding:"required"`}var req LoginRequestif err := c.ShouldBindJSON(&req); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if req.Username != "admin" || req.Password != "password" {c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的凭证"})return}token, err := generateToken(req.Username)if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "生成Token失败"})return}c.JSON(http.StatusOK, gin.H{"token": token,})
}// 认证中间件 - 检查请求中的Token
func authMiddleware() gin.HandlerFunc {return func(c *gin.Context) {tokenStr := c.GetHeader("Authorization")if tokenStr == "" || len(tokenStr) < 7 || tokenStr[:7] != "Bearer " {c.JSON(http.StatusUnauthorized, gin.H{"error": "缺少或格式错误的Token"})c.Abort()return}tokenStr = tokenStr[7:]claims, err := validateToken(tokenStr)if err != nil {c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的Token"})c.Abort()return}c.Set("username", claims.Username)c.Next()}
}// 受保护的接口 - 需要有效的Token才能访问
func protectedHandler(c *gin.Context) {username := c.MustGet("username").(string)c.JSON(http.StatusOK, gin.H{"message": "欢迎回来," + username,"data":    "这是受保护的数据",})
}func main() {r := gin.Default()r.POST("/login", loginHandler)authGroup := r.Group("/api")authGroup.Use(authMiddleware()){authGroup.GET("/protected", protectedHandler)}r.Run()
}

Apipost测试

curl -X POST http://localhost:8080/login \-H "Content-Type: application/json" \-d '{"username": "admin", "password": "password"}'

响应

{"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNjk5OTk5OTk5LCJpYXQiOjE2OTk5OTk2OTksImlzcyI6InlvdXItYXBwIn0.abcdefghijklmnopqrstuvwxyz123456"
}
然后
curl -X GET http://localhost:8080/api/protected \-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

var jwtKey = []byte("your-secret-key")  your-secret-key 可以随便写吗?

❶ 开发测试时:可以写简单的,但要注意
❷ 正式环境:必须用复杂、安全的密码
    • 比如用 your-secret-key 或 123456,方便测试代码是否正常运行。
    • 但千万不要在正式环境用这种简单密码!就像日记本用 “123456” 当密码,很容易被别人破解。
    • 规则
      • 长度至少 16 位,包含字母、数字、特殊符号(比如 !@#$%^&*())。
      • 不能是任何人都能猜到的内容(比如生日、名字)。

在 JWT 验证流程中,用密钥 “解锁” Token 的核心代码是 jwt.ParseWithClaims 函数。这个函数会验证 Token 的签名,并解析出其中的内容(Claims)。

// 定义Claims结构体用于存储解析结果
claims := &Claims{}// 用密钥"解锁"Token(验证签名并解析内容)
token, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil  // 返回密钥,用于验证签名
})

以下代码模拟了一个被篡改的 Token 的验证过程:

package mainimport ("fmt""github.com/dgrijalva/jwt-go"
)var jwtKey = []byte("your-secret-key")func main() {// 1. 生成一个合法的Tokenclaims := jwt.MapClaims{"username": "alice","exp":      jwt.TimeFunc().Add(time.Hour * 24).Unix(), // 24小时后过期}token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)tokenStr, _ := token.SignedString(jwtKey)fmt.Println("原始Token:", tokenStr)// 2. 模拟篡改Token(修改Payload中的username)// 注意:实际中无法直接修改,这里仅为演示验证失败的效果tamperedTokenStr := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImJvYiIsImV4cCI6MTY5OTQwNjQwMH0.abc123" // 伪造的Token// 3. 验证原始Token(正常情况)validToken, validErr := jwt.ParseWithClaims(tokenStr, jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil})fmt.Println("原始Token验证结果:", validToken.Valid, validErr)// 4. 验证篡改后的TokentamperedToken, tamperedErr := jwt.ParseWithClaims(tamperedTokenStr, jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil})fmt.Println("篡改Token验证结果:", tamperedToken.Valid, tamperedErr)
}

输出结果

原始Token验证结果: true <nil>
篡改Token验证结果: false signature is invalid

从 Token 中获取 username 的核心代码

1. 定义 Claims 结构体

首先需要定义一个结构体,用于存储 Token 中的数据:

type Claims struct {Username string `json:"username"`  // 对应Token中的username字段jwt.StandardClaims                  // 包含标准字段(如过期时间、签发者等)
}
2. 验证并解析 Token
// 验证Token并获取Claims
claims, err := validateToken(tokenStr)
if err != nil {// 处理验证失败的情况log.Fatal("Token验证失败:", err)
}// 从Claims中获取username
username := claims.Username
fmt.Println("用户名:", username)
3. 完整的验证函数示例
func validateToken(tokenStr string) (*Claims, error) {claims := &Claims{}token, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) {// 验证签名方法if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {return nil, fmt.Errorf("无效的签名方法: %v", token.Header["alg"])}// 返回密钥return jwtKey, nil})// 检查验证错误if err != nil {return nil, err}// 检查Token有效性if !token.Valid {return nil, errors.New("无效的Token")}return claims, nil
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87363.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

21、鸿蒙学习——使用App Linking实现应用间跳转

简介 使用App Linking进行跳转时&#xff0c;系统会根据接口传入的uri信息&#xff08;HTTPS链接&#xff09;将用户引导至目标应用中的特定内容&#xff0c;无论应用是否已安装&#xff0c;用户都可以访问到链接对应的内容&#xff0c;跳转体验相比Deep Linking方式更加顺畅。…

Cursor无限邮箱续费方法

1.注册无限邮箱2925 2.“其他邮箱” 3.点击左下角添加邮箱 4.管理员身份运行Windos PowerShell 5.输入该指令并运行&#xff0c;修改机器码 irm https://aizaozao.com/accelerate.php/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/…

LeetCode Hot100(图论)

200. 岛屿数量 题意 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外&#xff0c;你…

Ubuntu Gnome 安装和卸载 WhiteSur-gtk-theme 类 Mac 主题的正确方法

WhiteSur-gtk-theme 是一个流行的 GNOME 桌面主题&#xff0c;可以让 Ubuntu 的桌面环境看起来像 macOS。以下是安装和卸载 WhiteSur-gtk-theme 的详细步骤&#xff0c;包括解释每个命令的作用。 一、安装 WhiteSur-gtk-theme 1. 准备工作 在安装主题之前&#xff0c;建议确…

如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板

DataGear 数据可视化分析平台&#xff08;http://datagear.tech/&#xff09; 在新发布的5.4.1版本中&#xff0c;内置表格图表新增了serverSidePaging选项&#xff0c;仅需通过简单的配置&#xff0c;即可为表格添加服务端分页、关键字查询、排序功能。 本文以SQL数据集作为数…

股指期货套保比例怎么算?

在金融市场里&#xff0c;套期保值&#xff08;套保&#xff09;是一种常见的风险管理手段&#xff0c;目的是通过期货市场对冲现货市场的风险。而套保比例&#xff08;也叫套保比率&#xff09;的计算&#xff0c;是套保操作的核心。简单来说&#xff0c;套保比例就是“期货头…

逻辑回归(Logistic Regression)算法详解

文章目录 一、逻辑回归&#xff1a;从线性回归到二分类的跨越1.1 逻辑回归简介1.2 Sigmoid函数&#xff1a;概率映射的数学本质1.3 参数 w w w 和 b b b 对Sigmoid的调控1.4 从线性回归到分类1.5 决策边界&#xff1a;从概率到类别&#xff08;结合图3、图4&#xff09; 二、…

HTTPS通信流程:SSL/TLS握手全解析

2021&#xff0c;2022&#xff0c;2023年1-8月看了很多技术书籍&#xff0c;现在想来忘了很多&#xff0c;用到的也不多&#xff0c;但是因为提前接触过&#xff0c;所以很多新东西&#xff0c;接受起来&#xff0c;比预想的要容易些。最近突然想要回忆下HTTPS&#xff0c;居然…

SVG 在 VSCode 中的使用与优势

SVG 在 VSCode 中的使用与优势 引言 SVG(可缩放矢量图形)是一种基于可扩展标记语言的图形图像格式,与传统的位图格式(如 JPEG 或 PNG)相比,SVG 图像具有更高的灵活性和可缩放性。随着前端开发领域的不断发展,SVG 在网页设计中的应用越来越广泛。本文将介绍 SVG 在 Vis…

Ubuntu开放mysql 3306端口

Ubuntu开放mysql 3306端口 1. 检查 UFW 防火墙规则2. 检查 iptables 规则 1. 检查 UFW 防火墙规则 sudo ufw status verbose | grep 3306若输出包含 3306/tcp ALLOW&#xff0c;表示端口已开放(如下) ubuntuUbuntu2404:~$ sudo ufw status verbose | grep 3306 3306/tcp …

CentOS 卸载docker

1、停止docker服务 systemctl stop docker.socket systemctl stop docker systemctl stop containerd 2、列出已安装的docker包 yum list installed | grep -i docker 输出如下&#xff1a; containerd.io.x86_64 1.6.33-3.1.el7 docker-ce-stab…

MySQL数据库----DML语句

目录 DML-介绍SQL-DML-添加数据SQL-DML-修改数据SQL-DML-删除数据 DML-介绍 DML英文全称是 Data Manipulation Language(数据操作语言)&#xff0c;用来对数据库中表的数据记录进行增删改操作。 添加数据&#xff08;INSERT&#xff09; 修改数据&#xff08;UPDATE&#xff…

Prompt:提示词工程

前言在LLM大放异彩的今天&#xff0c;一个简单的问题&#xff0c;可能就会引出一个方案&#xff0c;一篇散文&#xff0c;而驱动这一切的&#xff0c;正是输入的“提示词&#xff08;Prompt&#xff09;”Prompt工程就是&#xff1a;与大模型打交道时&#xff0c;如何更好地设计…

GSAP 动画库在 Vue3 项目中的使用总结

前言 GSAP&#xff08;GreenSock Animation Platform&#xff09;是目前最强大的 JavaScript 动画库之一&#xff0c;以其出色的性能和简洁的API而闻名。本文将基于实际项目经验&#xff0c;详细介绍如何在 Vue3 项目中使用 GSAP 创建流畅、专业的动画效果&#xff0c;包括核心…

【字节跳动】数据挖掘面试题0007:Kmeans原理,何时停止迭代

文章大纲 K-means 原理与迭代停止条件⚙️ 一、K-Means核心思想&#x1f501; 二、迭代步骤详解关键数学操作 ⏹️ 三、何时停止迭代&#xff1f;Kmeans 算法实现代码 ⚠️ 四、面试常见扩展问题1. K值如何选择&#xff1f;2. 初始质心影响结果吗&#xff1f;3. 算法缺陷与改进…

209、长度最小的子数组

题目&#xff1a; 解答&#xff1a; 滑动窗口&#xff0c;左右指针指向窗口两端&#xff0c;窗口为[left,right]&#xff0c;leftright时窗口只包含一个元素。 窗口内元素和sum>target时&#xff0c;left,推出左侧一个元素;sum<target时&#xff0c;right&#xff0c;加…

关机精灵——自动化与便利性

文章目录 背景目标实现下载 背景 自动化与便利性&#xff1a; 让电脑在用户无需值守或干预的情况下&#xff0c;在特定时间点&#xff08;倒计时结束&#xff09;或任务完成后自动关闭。节能与环保&#xff1a; 避免电脑在完成工作后或无人使用时继续空耗电力。时间管理与健康…

L2CAP协议详解:分段重组、QoS控制与多协议复用设计(面试宝典)

本文系统解析L2CAP协议的知识图谱&#xff0c;掌握面试核心考点&#xff0c;并通过真题演练提升实战能力。建议配合协议分析工具进行抓包实践&#xff0c;加深对协议机制的理解。 一、L2CAP 在蓝牙协议栈中的核心定位 L2CAP&#xff08;Logical Link Control and Adaptation P…

微软服务器安全问题

微软云服务器安全深度解析&#xff1a;挑战、应对与未来展望——构建韧性“安全之盾”的持续博弈&#xff01; 在当今数字化时代&#xff0c;云计算已成为众多企业和组织运行业务的核心基础设施和“数字生命线”&#xff0c;而微软云&#xff08;Azure&#xff09;作为全球领先…

后台管理系统的诞生 - 利用AI 1天完成整个后台管理系统的微服务后端+前端

AI创作系列(11)&#xff1a;后台管理系统的诞生 - 利用AI 1天完成整个后台管理系统的微服务后端前端 真实记录&#xff1a;我决定为海狸IM添加一个后台管理系统。从早上开始&#xff0c;到晚上结束&#xff0c;仅仅1天时间&#xff0c;我就完成了整个后台管理系统的微服务后端和…