玩转Gin框架:Golang使用Gin完成登录流程

文章目录

    • 背景
    • 基于Token认证机制简介
    • 常见的Token类型
    • Token的生成和验证
      • 在项目工程里创建jwt.go文件
      • 根目录新建.env文件
    • 创建登录接口 /login
    • Token认证机制的优点

背景

登录流程,相信大家都很熟悉的。传统网站采用session后端验证登录状态,大致流程如下:

  • 用户输入用户名和密码 / 手机号和验证码点击登录按钮提交表单。
  • 后端校验前端传递过来的信息,验证通过在缓存中存储用户信息。
  • 后续每次请求时,携带session_id发送给服务端验证登录状态。

综上所述,一个简单的登录流程就完成了,但是你会发现在现如今session机制已无法满足一些服务架构,特别是在分布式服务和单点登录等功能使用session机制完成登录认证过程就需要解决共享session的问题,再者如果用户量很多,服务器内存压力会很大等等。

基于Token认证机制简介

Token 认证机制 是一种常用的身份验证方法,特别适用于现代化的 前后端分离 和 微服务架构 的应用。相比传统的 Session 认证机制,Token 认证具有一些明显的优势,特别是在 扩展性 和 跨平台 支持上,大致流程如下:
4. 客户端通过用户名和密码请求登录,后端对接收到的账号和密码进行验证
5. 如验证通过,则会签发一个Token返回给客户端进行存储
6. 后续客户端通过Authorization头部携带Token向服务器请求资源。

常见的Token类型

最常用的Token类型是JWT(JSON Web Token),它是一种自包含的、基于JSON格式的Token
JWT分为三个部分:

  1. Header(头部):
    • 通常包含Token类型(例如JWT)和所使用的签名算法(例如HS256)。
  2. Payload(负载):
    • 包含用户的相关信息(如用户ID、权限等)。这是Token的主体部分,不加密,因此可以被客户端解码,但签名确保其不被篡改。
  3. Signature(签名):
    • 由服务器端的密钥生成,用来验证Token的合法性和完整性。签名部分用于防止Token在传输过程中被篡改。

Token的生成和验证

在项目工程里创建jwt.go文件

参考路径:BackEnd/pkg/auth/jwt.go

package authimport ("errors""os""time""github.com/golang-jwt/jwt/v5""github.com/joho/godotenv"
)// Secret 从环境变量中加载 JWT 密钥
var jwtSecret = []byte(getJWTSecret())// getJWTSecret 从环境变量中获取 JWT 密钥
func getJWTSecret() string {// 加载.env文件if err := godotenv.Load(); err != nil {panic("无法加载 .env 文件,请确保文件存在并正确配置")}secret := os.Getenv("JWT_SECRET")if secret == "" {panic("环境变量 JWT_SECRET 未设置,请配置后再运行程序")}return secret
}// GenerateToken 生成 JWT Token
func GenerateToken(username string) (string, error) {claims := jwt.MapClaims{"username": username,"exp":      time.Now().Add(time.Hour).Unix(), // 一小时后过期"iat":      time.Now().Unix(),                // 签发时间}token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)return token.SignedString(jwtSecret)
}
// 验证签名时,通过解析 token ,验证 token 是否有效,再验证是否过期。验证Token 是用在用户登录后所有请求都需要携带 token ,然后服务端获取到 token 再进行验证过。
func ValidateToken(tokenString string) (jwt.MapClaims, error) {token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {return nil, errors.New("签名方法无效,请检查 Token 的生成方式")}return jwtSecret, nil})if err != nil {return nil, err}if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {return claims, nil}return nil, errors.New("无效的 Token,请重新登录获取有效的 Token")
}

根目录新建.env文件

该文件用于区分不同环境的参数和记录密钥等信息

JWT_SECRET=kklive

创建登录接口 /login

参考路径:BackEnd/internal/user/handle.go

package userimport ("database/sql""my-ecommerce-app/pkg/auth""net/http""github.com/gin-gonic/gin""golang.org/x/crypto/bcrypt"
)// Response 定义统一的响应结构
type Response struct {Code    int    `json:"code"`Message string `json:"message"`
}// UserLoginRequest 定义登录请求结构
type UserLoginRequest struct {Username string `json:"username" binding:"required"`Password string `json:"password" binding:"required"`
}// UserQueryRequest 查询用户请求结构
type UserQueryRequest struct {Username string `json:"username" binding:"required"`
}// UserQueryResponse 查询用户响应结构
type UserQueryResponse struct {ID         int    `json:"id"`Username   string `json:"username"`Nickname   string `json:"nickname"`Face       string `json:"face"`Email      string `json:"email"`Created_at string `json:"created_at"`
}// UserLoginResponse 定义登录成功的响应
type UserLoginResponse struct {Message string `json:"message"`Token   string `json:"token,omitempty"`Code    int    `json:"code"`
}// LoginHandler 用户登录接口
// @Summary 用户登录
// @Description 用户通过用户名和密码登录
// @Tags 用户模块
// @Accept json
// @Produce json
// @Param user body UserLoginRequest true "登录请求参数"
// @Success 200 {object} UserLoginResponse
// @Failure 400 {object} Response
// @Failure 401 {object} Response
// @Router /api/login [post]
func LoginHandler(db *sql.DB) gin.HandlerFunc {return func(ctx *gin.Context) {var req UserLoginRequestif err := ctx.ShouldBindJSON(&req); err != nil {ctx.JSON(http.StatusBadRequest, gin.H{"code":    401,"message": "参数错误",})return}var passwordHash stringerr := db.QueryRow("SELECT password FROM li_admin_user WHERE username = ?", req.Username).Scan(&passwordHash)if err != nil {if err == sql.ErrNoRows {ctx.JSON(http.StatusUnauthorized, gin.H{"code":    405,"message": "用户名或密码错误",})} else {ctx.JSON(http.StatusInternalServerError, gin.H{"code":    500,"message": "服务器错误",})}return}if err := bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(req.Password)); err != nil {ctx.JSON(http.StatusUnauthorized, gin.H{"code":    405,"message": "用户名或密码错误",})return}token, err := auth.GenerateToken(req.Username)if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"code":    500, // Token生成错误"message": "请重新登录",})return}ctx.JSON(http.StatusOK, UserLoginResponse{Code:    200,Message: "登录成功!",Token:   token,})}
}

Token认证机制的优点

使用Token进行无状态登录认证后,就可以轻松的实现多端登录和单点登录SSO,在签名算法中加入Token机器信息,就可以有效的控制账号的多端登录登出场景。

  • 支持多端同时登录,任意端退出登录时,其他端保持不变,每个端会生成自己的Token,并且相互独立
  • 支持多端同时登录,一端退出所有端退出登录,增加用户登录设备表,记录账号登录的设备和对应的Token信息,当一端点击退出时,在服务端删除缓存中的Token信息即可
  • 多端选择性退出部分端:退出登录时增加一个需要退出端的对应设备类型或者设备ID,然后对应设备下的token 进行失效处理。

当然,除了以上使用场景,还有其他的优点,欢迎在评论区一起交流~

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

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

相关文章

docker pull Error response from daemon问题

里面填写 里面解决方案就是挂代理。 以虚拟机为例,将宿主机配置端口设置,https/http端口设为7899 配置虚拟机的http代理: vim /etc/systemd/system/docker.service.d/http-proxy.conf里面填写,wq保存 [Service] Environment…

【Rust自学】17.2. 使用trait对象来存储不同值的类型

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 17.2.1. 需求 这篇文章以一个例子来介绍如何在Rust中使用trait对象来存储不同值的类型。 在第 8 章中,我们提到Vector的一个…

FocusAny v0.6.0 MacOS和Linux安装优化,独立窗口显示优化

FocusAny 是一个专注高效的AI工具条,可以使用 Alt / Option空格 一键唤起,通过插件快速安装,可以扩展出非常多的功能。 安装使用 访问 https://focusany.com 下载 对应系统 安装包,一键安装即可。 目前支持 Windows、MacOS、Linu…

Windows:AList+RaiDrive挂载阿里云盘至本地磁盘

零、前言 电脑存储的文件多了,出现存储空间不够用的情况。又没前买新的硬盘或者笔记本电脑没有额外的插槽提供给新的硬盘。遇到这种情况,我想到可以使用网盘,但单纯的网盘又要上传下载,极其麻烦。看到WPS云盘可以直接挂载本地&…

Redis缓存穿透、击穿、雪崩介绍以及解决方案

一、缓存穿透 1.1 什么是缓存穿透? 指的是,外部进来的请求,查询一个不存在的数据。Redis中没有,数据库中也没有,这时候如果外部恶意大量请求,所有请求会直接查询数据库,导致数据库崩溃 1.2 解决…

2025 持续防范 GitHub 投毒,通过 Sharp4SuoExplorer 分析 Visual Studio 隐藏文件

在2024年底的网络安全事件中,某提权工具被发现植入后门,攻击者利用 .suo 文件作为隐蔽的攻击方式。由于 .suo 文件是 Visual Studio 项目的隐藏配置文件,通常不为安全研究人员所关注,因此为攻击者提供了潜在的攻击渠道。 初步调查…

【Windows7和Windows10下从零搭建Qt+Leaflet开发环境】

Windows7和Windows10下从零搭建QtLeaflet开发环境 本文开始编写于2025年1月27日星期一(农历:腊月二十八,苦逼的人,过年了还在忙工作)。 第一章 概述 整个开发环境搭建需要的资源: 操作系统 Windows7_x6…

熵采样在分类任务中的应用

熵采样在分类任务中的应用 在机器学习的分类任务里,数据的标注成本常常制约着模型性能的提升。主动学习中的熵采样策略,为解决这一难题提供了新的思路。本文将带你深入了解熵采样在分类任务中的原理、应用及优势。 一、熵采样的原理(优化版) 熵,源于信息论,是对不确定…

WordPress自定义.js文件排序实现方法

在WordPress中,要将插件引用的.js文件放到所有.js文件之后加载,可以通过以下方法实现: 方法一:调整wp_enqueue_script的加载顺序 在插件的主文件中,使用wp_enqueue_script函数加载.js文件时,将$in_footer…

mysql 学习7 DCL语句,用来管理数据库用户,控制数据库的访问权限

DCL data control language 数据控制语言: 用来管理数据库用户,控制数据库的访问权限 有两个功能: 一,用户管理的SQL 语句,添加用户,删除用户,修改用户 查询用户 在mysql 中,用户…

8-登录流程

在AppStartInitFinish_CreateLoginUI.初始化后,执行Login界面的初始化 登录面板逻辑:UILoginComponentSystem,针对组件UILoginComponent创建的System 登录面板逻辑:UILoginComponent 逻辑层: LoginHelper中的clientSenderComponent.LoginA…

【远程控制】安装虚拟显示器

todesk远程发现没显示器的机器有问题 电脑如果不外接一个显示器那么会默认为1024 768 分辨率需要安装虚拟显示器参考 竟然是一个隐私屏幕的解决方案。 虚拟显示器 Parsec-vdd 项目地址 Parsec-vdd 最大的优点是:支持 4K 高刷、可添加多个虚拟屏、 H-Cursor&#…

【数据采集】基于Selenium采集豆瓣电影Top250的详细数据

基于Selenium采集豆瓣电影Top250的详细数据 Selenium官网:https://www.selenium.dev/blog/ 豆瓣电影Top250官网:https://movie.douban.com/top250 写在前面 实验目标:基于Selenium框架采集豆瓣电影Top250的详细数据。 电脑系统:Windows 使用软件:PyCharm、Navicat 技术需求…

安全实验作业

一 拓扑图 二 要求 1、R4为ISP,其上只能配置IP地址;R4与其他所有直连设备间均使用共有IP 2、R3-R5-R6-R7为MGRE环境,R3为中心站点; 3、整个OSPF环境IP基于172.16.0.0/16划分; 4、所有设备均可访问R4的环回&#x…

响应式编程_02基本概念:背压机制 Backpressure

文章目录 Pre流流的处理模型拉模式推模式 流量控制产者生产数据的速率小于消费者的场景生产者生产数据的速率大于消费者消费数据无界队列有界丢弃队列有界阻塞队列 背压机制响应式流规范响应式流的核心接口PublisherSubscriberSubscription 响应式流的技术生态圈 小结 Pre 响应…

Android 进程间通信

什么是IPC? Android 进程间通信(IPC,Inter-Process Communication)是Android操作系统中不同进程间交换数据和资源的一种机制。由于Android是多任务操作系统,每个应用通常运行在自己的进程中,以提高安全性和…

【人工智能】掌握图像风格迁移:使用Python实现艺术风格的自动化迁移

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 图像风格迁移(Image Style Transfer)是一种基于深度学习的计算机视觉技术,通过将一张图像的内容与另一张图像的艺术风格结合,生成一幅具…

Macos给brew安装的neo4j配置apoc插件

文章目录 打开并查看neo4j版本下载apoc插件安装apoc插件修改conf配置文件验证成果 打开并查看neo4j版本 open /usr/local/Cellar/neo4j下载apoc插件 apoc插件下载界面,选择与neo4j兼容的apoc版本apoc与neo4j版本对应表 安装apoc插件 将下载的apoc jar包&#…

回顾生化之父三上真司的游戏思想

1. 放养式野蛮成长路线,开创生存恐怖类型 三上进入capcom后,没有培训,没有师傅手把手的指导,而是每天摸索写策划书,老员工给出不行的评语后,扔掉旧的重写新的。 然后突然就成为游戏总监,进入开…

Go语言的转义字符

文章目录 1. Go语言的转义字符(escapechar)2. 小结和提示 1. Go语言的转义字符(escapechar) 说明:常用的转义字符有如下: \t : 表示一个制表符,通常使用它可以排版\n :换行符\\ :一个\\" :一个"\r :一个回…