【gin】中间件使用之jwt身份认证和Cors跨域,go案例

news2025/1/16 23:04:17

Gin-3 中间件编程及 JWT 身份认证

1. Gin 中间件概述

中间件是处理 HTTP 请求的函数,可以在请求到达路由处理函数之前或之后对请求进行处理。
在 Gin 框架中,中间件常用于处理日志记录、身份验证、权限控制等功能。

router := gin.Default()
router.Use(middleware) // 使用中间件

中间件可以通过 Use 方法进行添加,并且可以用于所有路由特定路由组

2. JWT 简介

https://github.com/golang-jwt/jwt

JSON Web Token(JWT)是一种用于认证和授权的标准。JWT 包含三个部分:

  1. 头部 (Header)
  2. 载荷 (Payload)
  3. 签名 (Signature)
JWT = Base64UrlEncode(HEADER) + "." + Base64UrlEncode(PAYLOAD) + "." + Base64UrlEncode(SIGNATURE)

JWT 的优点是自包含,它在用户和服务之间传递信息时不依赖于存储。
由于 JWT 包含所有必要的用户信息,服务端不需要保持用户的状态。

3. Gin 中的 JWT 身份认证实现

在 Gin 中实现 JWT 身份认证主要包含以下步骤:

  1. 生成 JWT Token:登录时生成 JWT Token。
  2. 验证 JWT Token:通过中间件验证请求中的 Token。
  3. 访问受保护路由:只有验证通过的用户才能访问受保护的路由。

3.1 JWT 生成与验证函数

通过以下代码,您可以生成和验证 JWT Token:

package jwt_plugin

import "github.com/golang-jwt/jwt/v5"

var key = "abcdefg123" // 用于加密和解密的密钥

// 数据结构,存储用户信息和标准声明
type Data struct {
    Name   string `json:"name"`
    Age    int    `json:"age"`
    Gender int    `json:"gender"`
    jwt.RegisteredClaims
}

// 生成 JWT Token
func Sign(data jwt.Claims) (string, error) {
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, data)
    sign, err := token.SignedString([]byte(key))
    if err != nil {
        return "", err
    }
    return sign, nil
}

// 验证 JWT Token
func Verify(sign string, data jwt.Claims) error {
    _, err := jwt.ParseWithClaims(sign, data, func(token *jwt.Token) (any, error) {
        return []byte(key), nil
    })
    return err
}

生成 JWT Token 时,我们会使用 Sign 函数,验证时使用 Verify 函数。
Sign 函数会将用户信息(载荷)和签名一起返回,Verify 函数用于验证 JWT Token 是否有效。

3.2 登录接口实现

用户登录时,通过 Login 函数生成 JWT Token,并返回给客户端。

package login

import (
    "github.com/gin-gonic/gin"
    "golang13-gin/jwt_plugin"
    "net/http"
    "time"
)

func Login(c *gin.Context) {
    // 用户信息及 JWT 载荷
    data := jwt_plugin.Data{
        Name:   "nick",
        Age:    18,
        Gender: 1,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
            NotBefore: jwt.NewNumericDate(time.Now()),
        },
    }
    
    // 生成 JWT Token
    sign, err := jwt_plugin.Sign(data)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "error": err.Error(),
        })
        return
    }

    // 返回 JWT Token
    c.JSON(http.StatusOK, gin.H{
        "access_token": sign,
    })
}

登录成功后,系统会返回一个包含用户信息和有效期的 JWT Token。

3.3 JWT 身份验证中间件

package middleware

import (
    "github.com/gin-gonic/gin"
    "golang13-gin/jwt_plugin"
    "net/http"
)

func Auth() gin.HandlerFunc {
    return func(c *gin.Context) {
        accessToken := c.Request.Header.Get("access_token") // 获取请求头中的 Token
        data := &jwt_plugin.Data{}
        err := jwt_plugin.Verify(accessToken, data) // 验证 Token
        if err != nil {
            c.JSON(http.StatusForbidden, gin.H{
                "error": "身份认证失败",
            })
            c.Abort() // 中止请求
        }
        c.Set("auth_info", data) // 将用户信息存储在上下文中
        c.Next() // 继续后续处理
    }
}

身份验证中间件 Auth 会从请求头中提取 JWT Token 并进行验证。如果验证失败,返回 403 错误;否则将用户信息存储到上下文,供后续路由使用。

4. CORS 中间件

CORS(跨域资源共享)允许服务器指定哪些源(Origin)可以访问资源。以下是设置 CORS 中间件的代码:

package middleware

import (
    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

func Cors() gin.HandlerFunc {
    return cors.New(cors.Config{
        AllowAllOrigins: true,
        AllowHeaders: []string{
            "Origin", "Content-Length", "Content-Type",
        },
        AllowMethods: []string{
            "GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS",
        },
    })
}

CORS 中间件配置允许来自任何来源的请求,并且可以处理指定的 HTTP 方法和头部。

5. 路由初始化与中间件使用

在 Gin 中,可以通过 Use 方法将中间件添加到路由组中,以下是一个例子:

func InitRoutes(r *gin.Engine) {   
    api := r.Group("/api")   
    api.Use(middleware.Cors(), middleware.Auth()) // 使用 CORS 和 JWT 验证中间件



    InitCourse(api)   
    InitUser(api)   
    InitUpload(api)   

    notAuthApi := r.Group("/api")   
    notAuthApi.Use(middleware.Cors())   
    InitLogin(notAuthApi) // 不需要身份验证的路由   
}

总结

概念描述代码示例
Gin 中间件中间件是一个函数,用来处理 HTTP 请求。在请求进入路由处理函数之前或之后,执行某些操作。router.Use(middleware)
JWT (JSON Web Token)一种用于认证和授权的标准格式,通过三个部分组成:头部、载荷和签名。它具有自包含特性,可以在分布式系统中使用。token := jwt.NewWithClaims(jwt.SigningMethodHS256, data)
JWT 生成通过载荷和密钥生成 JWT Token。sign, err := jwt_plugin.Sign(data)
JWT 验证通过 Token 验证用户身份,确保请求的合法性。err := jwt_plugin.Verify(accessToken, data)
身份认证中间件在请求到达目标路由之前,验证请求中的 JWT Token,确保只有通过验证的请求才能继续处理。func Auth() gin.HandlerFunc { return func(c *gin.Context) { ... } }
CORS 中间件解决浏览器跨域问题,允许不同域的请求访问服务器资源。func Cors() gin.HandlerFunc { return cors.New(cors.Config{ AllowAllOrigins: true }) }
路由组将具有共同前缀的路由放在一个组中,方便统一管理和中间件的应用。api := r.Group("/api")
JWT 载荷JWT 中的数据部分,包含用户信息和其他元数据。可以自定义内容,也可以使用预定义的注册声明(如过期时间)。RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)) }
路由配置定义与中间件、请求处理函数相关的路由。InitLogin(notAuthApi)

表格解释:

  1. Gin 中间件 是一类用于在路由处理函数执行前或后处理请求的函数,常见的中间件包括身份认证、中间件控制等。
  2. JWT 是一种 JSON 格式的认证方式,包含头部、载荷和签名,适用于分布式系统,解决了服务端无状态的问题。
  3. JWT 生成和验证 是通过特定的密钥和载荷数据生成的,可以通过库函数轻松实现生成和验证操作。
  4. 身份认证中间件 通过在请求处理中拦截请求并验证 JWT Token 是否有效来确保用户身份的合法性。
  5. CORS 中间件 允许不同来源的客户端发起请求,解决跨域问题,常见于前后端分离的应用场景。
  6. 路由组 可以帮助组织和管理具有共同特征的路由,通过给路由组添加中间件,使得多个路由共享特定的功能。
  7. JWT 载荷 中的数据部分,存储的是用户信息以及与身份认证相关的信息(如过期时间等)。

JWT载荷

JWT 载荷部分是什么,是否可有可无?
JWT 的载荷部分是存储在 Token 中的实际信息,它包含了 声明(claims),这些声明通常用于存储用户信息、权限、Token 的有效期等。
JWT 载荷部分包含以下几种类型的声明:

  • 注册声明(Registered Claims):如 exp(过期时间)、iat(签发时间)、sub(主题)等。
  • 公共声明(Public Claims):可以自定义,用于表示用户信息或其他数据。
  • 私有声明(Private Claims):由双方约定用于传递的信息。
    是否可有可无?

如果只是需要传递一个简单的标识符(如用户 ID),那么可以简化载荷部分。
但通常,JWT 的载荷是不可或缺的,因为它包含了 Token 的有效期、权限等重要信息。
如果载荷部分为空或缺少必要的字段,Token 的使用价值将大大降低。


https://github.com/0voice

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

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

相关文章

通信与网络安全管理之ISO七层模型与TCP/IP模型

一.ISO参考模型 OSI七层模型一般指开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。 它从低到高分别是…

Redis--21--大Key问题解决方案

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言Redis--20--大Key问题解析 一、如何发现Redis大Key1. 使用Redis命令行工具**MEMORY USAGE****RANDOMKEY****DEBUG OBJECT****SCAN命令****redis-cli 工具&#…

微信小程序订阅消息提醒-云函数

微信小程序消息订阅分2种: 1.一次性订阅:用户订阅一次就可以推送一次,如果需要多次提醒需要多次订阅。 2.长期订阅:只有公共服务领域,如政务、医疗、交通、金融和教育等。‌在用户订阅后,在很长一段时间内…

Ubuntu上,ffmpeg如何使用cuda硬件解码、编码、转码加速

本文使用 Ubuntu 环境。Ubuntu 直接使用 APT 安装的就支持 CUDA 加速。本文使用这样下载的版本进行演示,你自己编译或者其他源的版本可能会不同。 ffmpeg 的一些介绍,以及 macOS 版本的 ffmpeg 硬件加速请见《macOS上如何安装(不需要编译安装…

了解Python中的SciPy库

么是 SciPy? SciPy(发音为“Sigh Pie”)是 Scientific Python 的首字母缩写词,它是 Python 的开源库,用于科学和技术计算。它是 Python 编程语言中称为 Numpy 的基本数组处理库的扩展,旨在支持高级科学和工…

51单片机入门基础

目录 一、基础知识储备 (一)了解51单片机的基本概念 (二)掌握数字电路基础 (三)学习C语言编程基础 二、开发环境搭建 (一)硬件准备 (二)软件准备 三、…

【Qt】01-了解QT

踏入QT的殿堂之路 前言一、创建工程文件1.1 步骤介绍1.2 编译介绍方法1、方法2、编译成功 二、了解框架2.1 main.cpp2.2 .Pro文件2.2.1 注释需要打井号。2.2.2 F1带你进入帮助模式2.2.3 build文件 2.3 构造函数 三、编写工程3.1 main代码3.2 结果展示 四、指定父对象4.1 main代…

【Uniapp-Vue3】使用defineExpose暴露子组件的属性及方法

如果我们想要让父组件访问到子组件中的变量和方法,就需要使用defineExpose暴露: defineExpose({ 变量 }) 子组件配置 父组件配置 父组件要通过onMounted获取到子组件的DOM 传递多个属性和方法 子组件 父组件

qml XmlListModel详解

1、概述 XmlListModel是QtQuick用于从XML数据创建只读模型的组件。它可以作为各种view元素的数据源,比如ListView、GridView、PathView等;也可以作为其他和model交互的元素的数据源。通过XmlRole定义角色,如name、age和height,并…

登录系统网址作业

目录 主页代码 主页​编辑 效果1 登录页面代码 登录页面 效果2 注册页面代码 注册页面 效果3 主页代码 <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta name"viewport" content&qu…

生产管理看板助力节能科技公司实现数据自动化管理

在节能科技公司的生产过程中&#xff0c;数据管理的自动化是提高生产效率和产品质量的关键。然而&#xff0c;许多公司在数据记录、展示、对比和存档方面仍面临诸多痛点&#xff0c;如产品检测数据无法自动记录、缺乏直观的产线状态展示、检测数据对比繁琐耗时&#xff0c;以及…

论文阅读:Searching for Fast Demosaicking Algorithms

今天介绍一篇有关去马赛克的工作&#xff0c;去马赛克是 ISP 流程里面非常重要的一个模块&#xff0c;可以说是将多姿多彩的大千世界进行色彩还原的重要一步。这篇工作探索的是如何从各种各样的去马赛克算法中&#xff0c;选择最佳的一种。 Abstract 本文提出了一种方法&…

nginx 修改内置 404 页面、点击劫持攻击。

1、在部署前端项目的目录下增加 404.html 页面&#xff1a;/opt/web/404.html。 2、在 nginx 配置中增加 404 配置&#xff1a; root /opt/web; # 设置根目录的配置error_page 404 404.html; location /404.html {root /opt/web;# 指定 404 页面所在的根目录internal;# 确保…

金融项目实战 04|JMeter实现自动化脚本接口测试及持续集成

目录 一、⾃动化测试理论 二、自动化脚本 1、添加断言 1️⃣注册、登录 2️⃣认证、充值、开户、投资 2、可重复执行&#xff1a;清除测试数据脚本按指定顺序执行 1️⃣如何可以做到可重复执⾏&#xff1f; 2️⃣清除测试数据&#xff1a;连接数据库setup线程组 ①明确…

【SH】Xiaomi9刷Windows10系统研发记录 、手机刷Windows系统教程、小米9重装win10系统

文章目录 参考资料云盘资料软硬件环境手机解锁刷机驱动绑定账号和设备解锁手机 Mindows工具箱安装工具箱和修复下载下载安卓和woa资源包第三方Recovery 一键安装Windows准备工作创建分区安装系统 效果展示Windows和Android一键互换Win切换安卓安卓切换Win 删除分区 参考资料 解…

3 前端(上): Web开发相关概念 、HTML语法、CSS语法

文章目录 前言:导学1 Web开发相关概念2 Web标准(网页标准)3 软件架构(CS/BS)(1)C/S: Client/Server 客户端 / 服务器端(2)B/S: Browser/Server 浏览器 / 服务器端VSCode配置前段开发环境一、HTML概念1 概念2 HTML快速入门(1)语法快速入门(2)VSCode一个 !(快捷键…

Docker PG流复制搭建实操

目录标题 制作镜像1. 删除旧的容器2. 创建并配置容器3. 初始化数据库并启动 主库配置参数4. 配置主库5. 修改 postgresql.conf 配置 备库配置参数6. 创建并配置备库容器7. 初始化备库 流复制8. 配置&检查主库复制状态9. 检查备库配置 优化建议问题1&#xff1a;FATAL: usin…

【AIGC】SYNCAMMASTER:多视角多像机的视频生成

标题&#xff1a;SYNCAMMASTER: SYNCHRONIZING MULTI-CAMERA VIDEO GENERATION FROM DIVERSE VIEWPOINTS 主页&#xff1a;https://jianhongbai.github.io/SynCamMaster/ 代码&#xff1a;https://github.com/KwaiVGI/SynCamMaster 文章目录 摘要一、引言二、使用步骤2.1 TextT…

C++类与对象(一)—学习记录

序言&#xff1a;要想开发一款成功的应用程序&#xff0c;其开发者必须充分了解并实现用户的需求。作为一个设计良好的类&#xff0c;既要有直观且易于使用的接口&#xff0c;也必须具备高效的实现过程。 一、类与对象基本概念 面向对象程序设计的主要特点为抽象、封装、继承与…

【React】新建React项目

目录 create-react-app基础运用React核心依赖React 核心思想&#xff1a;数据驱动React 采用 MVC体系package.jsonindex.html好书推荐 官方提供了快速构建React 项目的脚手架&#xff1a; create-react-app &#xff0c;目前使用它安装默认是19版本&#xff0c;我们这里降为18…