12、Go Gin使用JWT实现认证机制

什么是JWT

JWT是JSON Web Token的缩写,是一种跨域认证的解决方案。 

使用JWT解决什么问题 

传统的登录认证的实现,依赖客户端浏览器的cookie和服务器的session,这种实现登录的方式有很大的局限性。

对于部署在单台服务器的应用来说,使用cookie+session登录认证的方案尚且可以接受。

但如果应用程序需要部署到多台服务器上呢?这里面就涉及到session的共享问题,另外,如果不同的域名想实现单点登录功能呢?显示cookie+session同样无法做到。

而要解决上面提出的问题,可以使用JWT,让应用变成无状态,避免session共享问题,而且可以很容易实现服务器的扩展。

JWT的格式 

一个正确的JWT格式如下所示:JWT字符串由Header,Payload,Signature三个部分组成,中间使用逗号连接

Header:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload:eyJpZCI6MTAwMDEsInVzZXJuYW1lIjoic2hpIiwiZXhwIjoxNzE1ODI2ODQ2LCJpc3MiOiJzaGkifQ

Signature:C6wT3MQVWVfMIVtOWEKbnY9yL9uWKV0Yi9yJJXrWIXw

完整token: 

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAwMDEsInVzZXJuYW1lIjoic2hpIiwiZXhwIjoxNzE1ODI2ODQ2LCJpc3MiOiJzaGkifQ.C6wT3MQVWVfMIVtOWEKbnY9yL9uWKV0Yi9yJJXrWIXw

Header(头部)

Header是一个JSON对象,由token类型和加密算法两个部分组成的

{
  "typ": "JWT",//默认为JWT
  "alg": "HS256"//支持多种加密算法
}

 将上面的JSON对象使用Base64URL算法转换成字符串,即可得到JWT中的Header部分

Base64 编码是一种将二进制数据编码为 ASCII 字符串的方法。然而,Base64 编码后的字符串中可能包含 +/= 这三个字符,这些字符在 URL 中有特殊含义:

  • + 字符在 URL 中用作分隔符。
  • / 字符在 URL 中用于分隔路径。
  • = 字符在 URL 中用作查询参数的赋值符号。

为了避免这些字符在 URL 中引起问题,JWT 使用了 Base64 URL 安全编码,它是 Base64 编码的一个变种,做了以下修改:

  • 将 + 替换为 -,这在 Base64 URL 编码中是常见的替换字符。
  • 将 / 替换为 _,这同样是为了 URL 安全。
  • 移除 =,这是 Base64 编码中的填充字符,用于确保编码后的字符串长度是 4 的倍数。在 Base64 URL 编码中,这个填充字符被省略,以避免在 URL 中使用。
Payload(有效信息、有效载荷)

JWT的Payload部分与Header一样,也是一个JSON对象,用来存放我们实际需要的数据,JWT标准提供了七个可选的字段,分别为:

除了标准的字段外,我们可以任意定义私有的字段以满足业务需求,如:

{
    iss:"my",//标准字段
    jti:"test",//标准字段
    username:"aaa",//自定义字段
    "gender":"男",
    "avatar":"https://1.jpg"
}

将上面的JSON对象使用Base64URL算法转换成字符串,即可得到JWT中的Payload部分。

Signature(签证)

Signature是JWT的签名,生成方式为:将Header与Payload进行Base64URL算法编码后,用逗号链接,再使用密钥(secretKey)和Header中指的加密方式进行加密,最终生成Signature。

JWT的特点

  1. 最好使用HTTPS协议,防止JWT被盗的可能。

  2. 除了JWT签发时间到期外,没有其他办法让已经生成的JWT失效,除非服务器端换算法。

  3. 在JWT不加密的情况下,JWT不应该存储敏感的信息,如果要存放敏感信息,最好再次加密。

  4. JWT最好设置较短的过期时间,防止被盗用后一直有效,降低损失。

  5. JWT的Payload也可以存储一些业务信息,这样可以减少数据库的查询。

JWT的使用

服务器签发JWT后,发送给客户端,客户端如果是浏览器的话,可以将其存放在cookie或localStorage中,如果是APP的话,则可以存放在sqlite数据库中。

然后每一次接口请求时都带上JWT,而带上来给服务端的方式,也有很多种,比如query、cookie、header或者body,总之就是一切可以带上数据给服务器的方式都可以,但比较规范的做还是通过header Authorization上传。

在Go项目中使用JWT

在Go项目中如何生成以及解析JWT,这里我们使用github.com/golang-jwt/jwt这个库来帮我们生成或解析JWT。

生成

使用NewWithClaims()方法生成Token对象,再通过Token对象的方法来生成JWT字符串
案例一
package main

import (
	"github.com/golang-jwt/jwt"
	"log"
	"time"
)

func main() {
	hmacSampleSecret := []byte("123qwe") //密钥,不能泄露
	//生成token对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"foo": "bar",
		"nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
	})
	//生成jwt字符串
	jwtString, err := token.SignedString(hmacSampleSecret)
	if err != nil {
		log.Fatal("签署JWT时出错", err)
	}
	log.Println("JWT String:", jwtString)
}
案例二  
package main

import (
	"github.com/golang-jwt/jwt" //也可以"github.com/dgrijalva/jwt-go"
	"log"
	"time"
)

/*
使用 JWT 库(如 github.com/dgrijalva/jwt-go、github.com/golang-jwt/jwt)可以创建和解析 JWT 令牌。
以下是使用 NewWithClaims 方法生成 JWT Token 对象,并通过该对象的方法生成 JWT 字符串
*/
func main() {
	// 定义 Claims
	//Claims 是 JWT 承载的有效信息,包括注册声明(如 iss, sub, aud 等)和自定义声明。您需要定义一个 map 或结
  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值