首页 > 其他分享 >实战:Go语言项目之使用JWT实现用户认证

实战:Go语言项目之使用JWT实现用户认证

时间:2024-12-25 16:58:44浏览次数:3  
标签:err jwt JWT 认证 go Token Go gin

实战:Go语言项目之使用JWT实现用户认证

基于cookie-Session 和基于token的认证模式

需求:请求分类

用户认证

HTTP 是一个无状态的协议,一次请求结束后,下次再发送,服务器就不知道这个请求是谁发过来的(同一个 IP 不代表同一个用户),在Web 应用中,用户的认证和鉴权是非常重要的一环,实践中有多种实现方案,各有千秋。

在 Web 应用发展的初期,大部分采用基于 Cookie - Session 的会话管理方式。逻辑如下:

  • 客户端使用用户名、密码进行认证
  • 服务端验证用户名、密码正确后生成并存储 Session,将SessionID 通过 Cookie 返回给客户端
  • 客户端访问需认证的接口时在 Cookie 中携带 SessionID
  • 服务端通过 SessionID 查找 Session 并进行鉴权,返回给客户端需要的数据

基于 Session 的方式存在多种问题

  • 服务端需要存储 Session,并且由于 Session 需要经常快速查找,通常存储在内存或内存数据库中,同时在线用户较多时需要占用大量的服务器资源。
  • 当需要扩展时,创建 Session 的服务器可能不是验证 Session 的服务器,所以还需要将所有Session 单独存储并共享。
  • 由于客户端使用 Cookie 存储 SessionID,在跨域场景下需要进行兼容性处理,同时这种方式也难以防范CSRF 攻击。

Token 认证模式

鉴于基于 Session 的会话管理方式存在上述多个缺点,基于 Token 的无状态会话管理方式诞生了,所谓无状态,就是服务端可以不再存储信息,甚至是不再存储Session。逻辑如下:

  • 客户端使用用户名、密码进行认证
  • 服务端验证用户名、密码正确后生成 Token 返回给客户端
  • 客户端保存 Token,访问需要认证的接口时在 URL 参数或 HTTP Header 中加入 Token
  • 服务端通过解码 Token 进行鉴权,返回给客户端需要的数据

基于 Token 的会话管理方式有效解决了基于 Session 的会话管理方式带来的问题。

  • 服务端不需要存储和用户鉴权有关的信息,鉴权信息会被加密到 Token 中,服务端只需要读取 Token 中包含的鉴权信息即可
  • 避免了共享 Session 导致的不易扩展问题
  • 不需要依赖 Cookie,有效避免 Cookie 带来的 CSRF 攻击问题
  • 使用 CORS 可以快速解决跨域问题

JWT 介绍

JWT 官网https://jwt.io/

JWT 文档https://jwt.io/introduction

JWT 是 JSON Web Token 的缩写,是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519)。JWT 本身没有定义任何技术实现,它只是定义了一种基于 Token 的会话管理的规则,涵盖 Token 需要包含的标准内容和 Token 的生成过程,特别适用于分布式站点的单点登录(SSO)场景。

JSON Web Token (JWT)是一个开放标准(RFC 7519) ,它定义了一种紧凑和自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。此信息可以进行验证和信任,因为它是经过数字签名的。JWT 可以使用机密(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

虽然可以对 JWT 进行加密,以便在各方之间提供保密性,但是我们将重点关注已签名的令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌可以向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,该签名还证明只有持有私钥的一方才是对其进行签名的一方。

下面是 JSON Web 令牌非常有用的一些场景:

  • Authorization 授权: 这是使用 JWT 最常见的场景。一旦用户登录,每个后续请求都将包含 JWT,允许用户访问该令牌所允许的路由、服务和资源。单点登录是目前广泛使用 JWT 的一个特性,因为它的开销很小,而且能够很容易地跨不同域使用。
  • Information Exchange 信息交换: JSON Web 令牌是在各方之间安全传输信息的好方法。因为可以对 JWT 进行签名(例如,使用公钥/私钥对) ,所以可以确保发件人就是他们所说的那个人。此外,由于签名是使用头和有效负载计算的,因此还可以验证内容是否被篡改。

一个 JWT Token 就像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JSON Web Token由以点(.)分隔的三个部分组成,它们是:

  • Header 头部
  • Payload 负载
  • Signature 签名

因此,JWT 通常如下所示。

xxxxx.yyyyy.zzzzz

Header通常由两部分组成: 令牌的类型(即 JWT)和所使用的签名算法(如 HMAC SHA256或 RSA)。

For example:

{
  "alg": "HS256",
  "typ": "JWT"
}

然后,对这个 JSON 进行 Base64Url 编码,形成 JWT 的第一部分。

Payload

Payload 表示负载,也是一个 JSON 对象,JWT 规定了 7 个官方字段供选用:

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
"nbf" (Not Before):生效时间
"iat" (Issued At) :签发时间
"jti" (JWT ID):编号

https://datatracker.ietf.org/doc/html/rfc7519#section-4.1

除了官方字段,开发者也可以自己指定字段和内容,例如下面的内容。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后对有效 payload 进行 Base64Url 编码,形成 JSON Web Token的第二部分。

请注意,对于已签名的令牌,这些信息虽然受到保护,不会被篡改,但任何人都可以阅读。除非加密,否则不要将机密信息放在 JWT 的有效负载或头元素中。

Signature

signature 部分是对前两部分的签名,防止数据篡改。

首先需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄漏给用户。然后使用Header 里面指定的签名算法(默认是 HMAC SHA256)。

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

要创建签名部分,您必须获取编码的标头、编码的有效载荷、秘密、标头中指定的算法,并对其进行签名。

例如,如果您想使用 HMAC SHA256算法,签名将按以下方式创建:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

该签名用于验证消息在执行过程中没有被更改,并且,对于使用私钥签名的令牌,它还可以验证 JWT 的发送方是否就是它所说的那个人。

Putting all together

输出是三个由点分隔的 Base64-URL 字符串,这些字符串可以在 HTML 和 HTTP 环境中轻松传递,同时与基于 XML 的标准(如 SAML)相比更加紧凑。

The following diagram shows how a JWT is obtained and used to access APIs or resources:

How does a JSON Web Token work

  1. The application or client requests authorization to the authorization server. This is performed through one of the different authorization flows. For example, a typical OpenID Connect compliant web application will go through the /oauth/authorize endpoint using the authorization code flow.
  2. When the authorization is granted, the authorization server returns an access token to the application.
  3. The application uses the access token to access a protected resource (like an API).

JWT 优缺点

JWT 拥有基于 Token 的会话管理方式所拥有的一切优势,不依赖 Cookie,使得其可以防止 CSRF 攻击,也能在禁用 Cookie 的浏览器环境中正常运行。

而 JWT 的最大优势是服务端不再需要存储 Session,使得服务端认证鉴权业务可以方便扩展,避免存储 Session 所需要引入的 Redis 等组件,降低了系统架构复杂度。但这也是 JWT 最大的劣势,由于有效期存储在 Token 中,JWT Token 一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的 JWT Token,如果需要禁用用户,单纯使用 JWT 就无法做到了。

基于 JWT 实现认证实践

前面说的 Token,都是 Access Token,也就是访问资源接口时所需要的 Token,还有另外一种 Token,Refresh Token,通常情况下,Refresh Token 的有效期会比较长,而 Access Token 的有效期比较短,当 Access Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Access Token,如果 Refresh Token 也失效了,用户就只能重新登陆了。

使用JWT实现用户认证

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

安装指南

  1. 要安装 jwt 包,首先需要安装 Go,然后可以使用下面的命令在 Go 程序中添加 jwt-Go 作为依赖项。
go get -u github.com/golang-jwt/jwt/v5
  1. Import it in your code:
import "github.com/golang-jwt/jwt/v5"

golang-jwt docshttps://golang-jwt.github.io/jwt/usage/create/

https://github.com/appleboy/gin-jwt

项目实操

项目目录

goblog on  main [!?] via 

标签:err,jwt,JWT,认证,go,Token,Go,gin
From: https://www.cnblogs.com/QiaoPengjun/p/18630890

相关文章

  • 08 Django - Django媒体文件&静态文件&文件上传
    九、Django媒体文件&静态文件&文件上传1.静态文件和媒体文件媒体文件:用户上传的文件,叫做media静态文件:存放在服务器的css,js,image等,叫做static在Django中使用静态文件{%static'img/example.jpg'%}=>static模板关键字就是在settings.py中指定的静态文件......
  • 项目管理专业人员PMP认证超全详解,打造职场核心竞争力!
    PMP认证介绍PMP®指的是项目管理专业人士资格认证,它是由美国计算机协会(ProjectManagementInstitute,简称PMI®)发起的,PMP®认证是严格评估项目管理人员知识技能是否具有高品质的资格认证考试。是目前全球项目管理方面含金量最高的资格认证,也是项目管理专业人士身份的象征。......
  • Go语言基础数据类型详解:整型、浮点型、复数与字符串
    Go语言基础数据类型详解:整型、浮点型、复数与字符串Go语言作为一门静态强类型的语言,其数据类型设计简洁而高效。掌握Go的基本数据类型是每个开发者深入理解Go语言的基础。本篇文章将详细介绍Go语言中最常见的基本数据类型,包括整型、浮点型、复数、布尔型、字符串等,并结合实例代码......
  • 数据同步工具: mysql表级全量同步 / mongodb全量+增量同步 / redis全量+增量同步
    目录数据同步工具方案说明MySql同步方案概述配置说明MongoDB同步方案概述配置说明Redis同步方案概述配置说明启动同步服务文件准备启动服务数据同步工具mysql表级全量同步/mongodb全量+增量同步/redis全量+增量同步源码地址:https://github.com/jiashuaizhang/sync-jobs......
  • mongodb配置zabbix监控
    mongodb配置zabbix监控目录mongodb配置zabbix监控说明一、添加mongodb模版二、配置宏三测试连接:注意事项通过脚本方式添加监控项1.修改运行zabbixagent脚本的用户2.添加如下用户自定义脚本3.添加如下用户自定义脚本附脚本:db_monitor.confjkalert.shjkcur_connect.shjkdelay.shjk......
  • Golang微服务-protobuf
    protobufgRPC是一款语言中立、平台中立、开源的远程过程调用系统,gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用数据在进行网络传输的时候,需要进行序列化,序列化协议有很多种,比如xml,json,protobuf等gRPC默认使用protocolbuff......
  • 域名实名认证信息有误,无法登录备案管理系统,如何解决?
    您在尝试登录备案管理系统时遇到实名认证信息有误的问题。以下是详细的解决方案:确认实名认证信息:确认提交的实名认证信息是否准确无误,包括姓名、身份证号码、联系方式等。确保所有信息与实际情况一致,避免因信息不符导致认证失败。找回登录账号和密码:如果忘记备案登录账......
  • GO: 结构体字段后面的 `json` 标注
    在Go语言中,在Go语言中,结构体字段后面的json标注是用来指定字段在JSON数据中的名称和处理方式。这个标注告诉Go的encoding/json包在序列化(将结构体转换为JSON)和反序列化(将JSON转换为结构体)时,如何映射结构体的字段与JSON数据中的键。JSON标注的基本语法:type......
  • 深入了解 Google Test (gtest):一份详细的指南
    GoogleTest(gtest)是Google提供的一款C++测试框架,它广泛应用于C++项目的单元测试。无论是初学者还是经验丰富的开发者,gtest都是一个强大而灵活的工具,能够帮助你编写和执行单元测试,确保你的代码质量和稳定性。本文将从gtest的基本概念到高级特性,逐步带你深入了解如何使用它......
  • Json转换工具类(基于google的Gson和阿里的fastjson)
    Json转换工具类(基于google的Gson和阿里的fastjson)|Id|Title|DateAdded|SourceUrl|PostType|Body|BlogId|Description|DateUpdated|IsMarkdown|EntryName|CreatedTime|IsActive|AutoDesc|AccessPermission||-------------|-------------|-------......