Golang Gin系列-7:认证和授权
在本章中,我们将探讨Gin框架中身份验证和授权的基本方面。这包括实现基本的和基于令牌的身份验证,使用基于角色的访问控制,应用中间件进行授权,以及使用HTTPS和漏洞防护保护应用程序。

实现身份认证
Basic 认证
Basic 认证是内置于HTTP协议中的简单身份验证方案。它包括在每个请求中发送用户名和密码。尽管它很容易实现,但出于安全考虑,不建议将其用于生产环境应用程序。
示例:Basic 认证
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()authorized := r.Group("/", gin.BasicAuth(gin.Accounts{"admin": "password123",}))authorized.GET("/protected", func(c *gin.Context) {user := c.MustGet(gin.AuthUserKey).(string)c.JSON(http.StatusOK, gin.H{"user": user, "message": "Welcome to the protected route!"})})r.Run()
}
在这个例子中,杜松子酒。BasicAuth中间件检查有效的用户名和密码。如果凭证正确,则继续请求;否则,它返回401 Unauthorized状态。
Token-based认证
Token-based认证,特别是使用JSON Web令牌(JWT),是一种更安全、可扩展的方法。jwt是无状态的,这意味着服务器不需要存储会话信息。

示例:Token-based认证
在本例中,“login”端点为有效凭证生成JWT,“authenticateJWT”中间件检查token的有效性。
package mainimport ("github.com/gin-gonic/gin""github.com/dgrijalva/jwt-go""net/http""time"
)var jwtKey = []byte("my_secret_key")type Claims struct {Username string `json:"username"`jwt.StandardClaims
}func main() {r := gin.Default()r.POST("/login", login)r.GET("/protected", authenticateJWT(), protected)r.Run()
}func login(c *gin.Context) {var creds struct {Username string `json:"username"`Password string `json:"password"`}if err := c.ShouldBindJSON(&creds); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})return}if creds.Username == "admin" && creds.Password == "password123" {expirationTime := time.Now().Add(5 * time.Minute)claims := &Claims{Username: creds.Username,StandardClaims: jwt.StandardClaims{ExpiresAt: expirationTime.Unix(),},}token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)tokenString, err := token.SignedString(jwtKey)if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not generate token"})return}c.JSON(http.StatusOK, gin.H{"token": tokenString})} else {c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"})}
}func authenticateJWT() gin.HandlerFunc {return func(c *gin.Context) {tokenString := c.GetHeader("Authorization")claims := &Claims{}token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {return jwtKey, nil})if err != nil || !token.Valid {c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})c.Abort()return}c.Set("username", claims.Username)c.Next()}
}func protected(c *gin.Context) {username := c.MustGet("username").(string)c.JSON(http.StatusOK, gin.H{"message": "Welcome to the protected route!", "user": username})
}
r.GET("/protected", authenticateJWT(), protected):定义 GET 请求的路由/protected,这是受保护的路由,请求会先经过authenticateJWT中间件进行 JWT 验证,验证通过后再由protected函数处理。- login()方法首先定义一个匿名结构体
creds用于接收客户端发送的 JSON 格式的用户名和密码。 c.ShouldBindJSON(&creds):尝试将客户端发送的 JSON 数据绑定到creds结构体上,如果绑定失败则返回 HTTP 400 错误。- 检查用户名和密码是否正确,如果正确则生成一个 JWT。
expirationTime:设置 JWT 的过期时间为当前时间加上 5 分钟。claims:创建一个Claims结构体实例,包含用户名和过期时间。jwt.NewWithClaims(jwt.SigningMethodHS256, claims):使用 HS256 算法创建一个新的 JWT。token.SignedString(jwtKey):使用jwtKey对 JWT 进行签名,生成 JWT 字符串。- 如果签名成功,将 JWT 字符串作为响应返回给客户端;否则返回 HTTP 500 错误。
- 如果用户名或密码不正确,返回 HTTP 401 错误。
授权技术

基于角色的访问控制
RBAC (Role-based access control)是一种基于角色的访问控制技术。这种方法可以有效地管理不同级别用户的权限。
示例:基于角色的访问控制
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()admin := r.Group("/admin", roleMiddleware("admin"))admin.GET("/dashboard", adminDashboard)r.Run()
}func roleMiddleware(role string) gin.HandlerFunc {return func(c *gin.Context) {userRole := c.GetHeader("Role")if userRole != role {c.JSON(http.StatusForbidden, gin.H{"error": "Access forbidden"})c.Abort()return}c.Next()}
}func adminDashboard(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "Welcome to the admin dashboard!"})
}
在这个例子中,roleMiddleware 检查用户是否有合适的角色来访问路由。
授权的中间件
中间件功能可用于集中处理授权逻辑,从而更容易管理整个应用程序的访问控制。
示例:授权的中间件
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.Use(authMiddleware)r.GET("/profile", userProfile)r.Run()
}func authMiddleware(c *gin.Context) {token := c.GetHeader("Authorization")if token != "valid-token" {c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})c.Abort()return}c.Next()
}func userProfile(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "User profile"})
}
在本例中,authMiddleware检查请求是否为有效的授权 token。
应用程序安全
HTTPS设置
设置HTTPS对于通过加密客户机和服务器之间交换的数据来保护应用程序至关重要。
示例:HTTPS设置
要设置HTTPS,你需要有效的SSL证书。出于开发目的,可以使用自签名证书。
package mainimport ("github.com/gin-gonic/gin""log"
)func main() {r := gin.Default()// Your routes here// Replace with your certificate and key fileserr := r.RunTLS(":443", "server.crt", "server.key")if err != nil {log.Fatal("Failed to start server: ", err)}
}
在本例中,RunTLS方法使用提供的证书和密钥文件以HTTPS启动服务器。
预防常见安全漏洞
防止SQL注入
始终使用参数化查询或ORM库来防止SQL注入攻击。
package mainimport ("github.com/gin-gonic/gin""net/http""database/sql"_ "github.com/go-sql-driver/mysql"
)func main() {r := gin.Default()db, err := sql.Open("mysql", "user:password@/dbname")if err != nil {panic(err)}r.GET("/user/:id", func(c *gin.Context) {id := c.Param("id")var name stringerr := db.QueryRow("SELECT name FROM users WHERE id = ?", id).Scan(&name)if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "User not found"})return}c.JSON(http.StatusOK, gin.H{"name": name})})r.Run()
}
在本例中,查询使用参数化语句来防止SQL注入。这里的 ? 是占位符,db.QueryRow 方法会先把 SQL 语句发送给数据库进行预编译,之后再把 id 作为参数传递给数据库。数据库会把参数当作普通的数据来处理,而不会将其作为 SQL 语句的一部分进行解析,这样就能有效防止恶意用户通过构造特殊输入来改变 SQL 语句的逻辑,进而避免 SQL 注入。
如果代码没有使用预编译语句,而是直接把用户输入拼接到 SQL 语句中,例如:
query := "SELECT name FROM users WHERE id = " + id
err := db.QueryRow(query).Scan(&name)
这种情况下,若恶意用户将 id 设置为特殊的值,如 1 OR 1=1,那么拼接后的 SQL 语句就会变成 SELECT name FROM users WHERE id = 1 OR 1=1,这样会使查询条件恒为真,从而可能导致数据库中的敏感信息被泄露,这就是 SQL 注入的危害。
防止跨站脚本(XSS)
清除任何用户输入以防止XSS攻击。使用像“blumonday”这样的库来清理HTML输入。
package mainimport ("github.com/gin-gonic/gin""github.com/microcosm-cc/bluemonday"
)func main() {r := gin.Default()r.POST("/comment", func(c *gin.Context) {comment := c.PostForm("comment")policy := bluemonday.UGCPolicy()sanitizedComment := policy.Sanitize(comment)c.JSON(200, gin.H{"comment": sanitizedComment})})r.Run()
}
在本例中,用户输入在使用之前被清理。
最后总结
通过遵循本章概述的实践,你可以在Gin应用程序中实现健壮的身份验证和授权机制,确保它们是安全可靠的。Gin,愈学习愈快乐, Go!
相关文章:
Golang Gin系列-7:认证和授权
在本章中,我们将探讨Gin框架中身份验证和授权的基本方面。这包括实现基本的和基于令牌的身份验证,使用基于角色的访问控制,应用中间件进行授权,以及使用HTTPS和漏洞防护保护应用程序。 实现身份认证 Basic 认证 Basic 认证是内置…...
mysql create table的用法
在MySQL中创建表的基本语法如下: CREATE TABLE table_name (column1 datatype,column2 datatype,column3 datatype,... );这里是一个例子,假设我们要创建一个名为employees的表,包含以下字段: id:一个整数类型的主键…...
蓝桥杯算法赛第25场月赛
前言 这些题对于我的难度有点大,大家感兴趣的可以来做一下,看一下,下面给大家展示一下题目 1. 桃花运走向【算法赛】 问题描述 2025 年春节,小明和小红兴致勃勃地去庙会玩耍。庙会上,一个算命先生摆摊算命…...
从介词到状语 (什么都研究一点系列)
契子 英语中介词的使用频率很高, 但在使用时本质上作为状语而成为句子成分, 没错 “本质上” 这三个字就是状语 😃 形式上是这样: 介词 -> 状语 -> 句子 常见的介词: 时间 at, 地点 on, 原因 of, 方式 in, 伴随 with, 比较 than, 条件 if 等等 下面我们开…...
CVE-2025-0411 7-zip 漏洞复现
文章目录 免责申明漏洞描述影响版本漏洞poc漏洞复现修复建议 免责申明 本文章仅供学习与交流,请勿用于非法用途,均由使用者本人负责,文章作者不为此承担任何责任 漏洞描述 此漏洞 (CVSS SCORE 7.0) 允许远程攻击者绕…...
java入门笔记基础语法篇(4)
变量 在Java中,每个变量都有一个类型(type)。在声明变量时,变量的类型位于变量 名之前。例如: int days; double salary; long earthPopulation; boolean done; 在Java中,每个声明以分号结束。变量名必须…...
学习数据结构(1)时间复杂度
1.数据结构和算法 (1)数据结构是计算机存储、组织数据的方式,指相互之间存在⼀种或多种特定关系的数据元素的集合 (2)算法就是定义良好的计算过程,取一个或一组的值为输入,并产生出一个或一组…...
存储基础 -- SCSI命令格式与使用场景
SCSI命令格式与使用场景 1. SCSI命令描述符块(CDB) 1.1 CDB基本概念 SCSI命令通过**命令描述符块(CDB, Command Descriptor Block)**表示。 CDB长度:SCSI命令根据使用场景有不同长度的CDB,常见的有6字节…...
PyTorch广告点击率预测(CTR)利用深度学习提升广告效果
目录 广告点击率预测问题数据集结构广告点击率预测模型的构建1. 数据集准备2. 构建数据加载器3. 构建深度学习模型4. 训练与评估 总结 广告点击率预测(CTR,Click-Through Rate Prediction)是在线广告领域中的重要任务,它帮助广告平…...
算法每日双题精讲 —— 二分查找(寻找旋转排序数组中的最小值,点名)
🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧💪 在算法的…...
Flutter TextPainter 计算文本高度和行数
在开发中有的时候需要去计算文本的高度或者行数,从而控制展示的内容,比如进一步设置展示控件的高度,或者根据行数进行不同的内容展示。 在原生 Android 开发时,View 的绘制流程分为 measure,layout,draw 三…...
STM32-时钟树
STM32-时钟树 时钟 时钟...
算法知识补充2
一部分:Tire树:高效地存储和查找字符串集合的数据结构acwing835 #include<iostream> #include<cstring> using namespace std; const int N100010; int son[N][26],cnt[N],idx; char str[N]; void insert(char str[]){int p0;for(int i0;st…...
微信小程序-点餐(美食屋)02开发实践
目录 概要 整体架构流程 (一)用户注册与登录 (二)菜品浏览与点餐 (三)订单管理 (四)后台管理 部分代码展示 1.index.wxml 2.list.wxml 3.checkout.wxml 4.detail.wxml 小结优点 概要…...
WPF基础 | WPF 常用控件实战:Button、TextBox 等的基础应用
WPF基础 | WPF 常用控件实战:Button、TextBox 等的基础应用 一、前言二、Button 控件基础2.1 Button 的基本定义与显示2.2 按钮样式设置2.3 按钮大小与布局 三、Button 的交互功能3.1 点击事件处理3.2 鼠标悬停与离开效果3.3 按钮禁用与启用 四、TextBox 控件基础4.…...
CentOS7使用源码安装PHP8教程整理
CentOS7使用源码安装PHP8教程整理 下载安装包解压下载的php tar源码包安装所需的一些依赖扩展库安装前的配置修改配置文件1、进入php8的安装包 配置环境变量开机自启启动服务创建软连接常见问题1、checking for icu-uc > 50.1 icu-io icu-i18n... no2、configure: error: Pa…...
强化学习 - 基于策略搜索和策略优化: 高斯策略
最近在做毕设需要用强化学习来做控制,对强化学习的知识点做一下总结。 高斯策略 高斯策略属于强化学习中的基于策略优化的分支(Policy Optimization),尤其是策略梯度方法(Policy Gradient Methods) 的一部…...
126周日复盘 (166)本周回顾
关键词:帧数测试 1、上午继续各处排查,优化帧数。 中午打包测试。 显卡锁60帧,720p窗口模式,画质3下, 低负载时50-60帧,密集战斗时35-45帧,基本达到预期, 硬件占用,显…...
08-Elasticsearch
黑马商城作为一个电商项目,商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的,存在很多问题。 首先,查询效率较低。 由于数据库模糊查询不走索引,在数据量较大的时候,查询性能很…...
SQL在DBA手里-改写篇
背景 最近运营需要做月报汇总交易情况,之前一直是他们手工出的数据,他们想做成月初自动发送邮件,从而减轻他们的工作量。于是他们提供SQL我们在邮件服务器配置做定时发送任务。 表介绍(表及字段已做脱敏处理) trans…...
02-机器学习-核心概念
以下是机器学习核心概念的详细梳理。 1. 机器学习三大范式 类型定义典型应用监督学习使用带标签的数据训练模型,预测未知数据的标签。分类(邮件垃圾过滤)、回归(房价预测)无监督学习从无标签的数据中发现隐藏模式或结…...
企业财务管理系统的需求设计和实现
该作者的原创文章目录: 生产制造执行MES系统的需求设计和实现 企业后勤管理系统的需求设计和实现 行政办公管理系统的需求设计和实现 人力资源管理HR系统的需求设计和实现 企业财务管理系统的需求设计和实现 董事会办公管理系统的需求设计和实现 公司组织架构…...
Couchbase UI: Server
在 Couchbase UI 中的 Server(服务器)标签页主要用于管理和监控集群中的各个节点。以下是 Server 标签页的主要内容和功能介绍: 1. 节点列表 显示集群中所有节点的列表,每个节点的详细信息包括: 节点地址࿱…...
【软件设计师中级】-笔记缩减版本-计算机系统基础知识
1. 计算机系统基础知识 1.1. 计算机系统硬件基本组成硬件 中央处理器(CPU)硬件系统的核心 运算器 控制器 存储器(记忆设备) 内部存储器(速度高,容量小):临时存放程序、数据及中间结…...
SAP MM 记录一次SAP外协采购收货提示 这种物料的特殊库存 O 0100003359 14019002不存在的问题
根据采购订单收货,调用时 BAPI_GOODSMVT_CREATE时返回 { "TYPE":"E", "ID":"M7", "NUMBER":"076", "MESSAGE":"这种物料的特殊库存 O 0100003359 14019002不存在"…...
2025牛客寒假算法基础集训营2
H 一起画很大的圆! 看起来像是一道计算几何的题,实际上通过分析和猜想,是有O1复杂度的结论的。具体证明略,结论是三点越接近共线,得出的半径越大。 #include <bits/stdc.h> using namespace std; #define endl \…...
统计学中的样本概率论中的样本
不知道当初谁想的把概率论和数理统计合并,作为一门课。这本身是可以合并,完整的一条线,看这里。但是,作为任课老师应该从整体上交代清楚,毕竟是两个学科,不同的学科合并必然会有各种不协调的问题。 举个最…...
DDD-全面理解领域驱动设计中的各种“域”
一、DDD-领域 在领域驱动设计(Domain-Driven Design,DDD)中,**领域(Domain)**指的是软件系统所要解决的特定业务问题的范围。它涵盖了业务知识、规则和逻辑,是开发团队与领域专家共同关注的核心…...
在 Ubuntu22.04 上安装 Splunk
ELK感觉太麻烦了,换个日志收集工具 Splunk 是一种 IT 工具,可帮助在任何设备上收集日志、分析、可视化、审计和创建报告。简单来说,它将“机器生成的数据转换为人类可读的数据”。它支持从虚拟机、网络设备、防火墙、基于 Unix 和基于 Windo…...
计算机网络 (60)蜂窝移动通信网
一、定义与原理 蜂窝移动通信网是指将一个服务区分为若干蜂窝状相邻小区并采用频率空间复用技术的移动通信网。其原理在于,将移动通信服务区划分成许多以正六边形为基本几何图形的覆盖区域,称为蜂窝小区。每个小区设置一个基站,负责本小区内移…...
