徐锦洪 发表于 2024-12-25 15:39:10

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

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

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

需求:请求分类
用户认证

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

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

[*]客户端利用用户名、密码举行认证
[*]服务端验证用户名、密码正确后天生并存储 Session,将SessionID 通过 Cookie 返回给客户端
[*]客户端访问需认证的接口时在 Cookie 中携带 SessionID
[*]服务端通过 SessionID 查找 Session 并举行鉴权,返回给客户端需要的数据
https://raw.githubusercontent.com/qiaopengjun5162/blogpicgo/master/img202306231831221.png
基于 Session 的方式存在多种问题

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

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

[*]客户端利用用户名、密码举行认证
[*]服务端验证用户名、密码正确后天生 Token 返回给客户端
[*]客户端保存 Token,访问需要认证的接口时在 URL 参数或 HTTP Header 中加入 Token
[*]服务端通过解码 Token 举行鉴权,返回给客户端需要的数据
https://raw.githubusercontent.com/qiaopengjun5162/blogpicgo/master/img202306231851685.png
基于 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_adQssw5cJSON Web Token由以点(.)分隔的三个部分组成,它们是:

[*]Header 头部
[*]Payload 负载
[*]Signature 签名
因此,JWT 通常如下所示。
xxxxx.yyyyy.zzzzzHeader

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:
https://cdn2.auth0.com/docs/media/articles/api-auth/client-credentials-grant.png

[*]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.
[*]When the authorization is granted, the authorization server returns an access token to the application.
[*]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 中,JWTToken 一旦签发,就会在有效期内不停可用,无法在服务端废止,当用户举行登出操作,只能依赖客户端删除掉当地存储的 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-jwt:https://github.com/golang-jwt/jwt
安装指南


[*]要安装 jwt 包,起首需要安装 Go,然后可以利用下面的下令在 Go 程序中添加 jwt-Go 作为依赖项。
go get -u github.com/golang-jwt/jwt/v5
[*]Import it in your code:
import "github.com/golang-jwt/jwt/v5"golang-jwt docs:https://golang-jwt.github.io/jwt/usage/create/
https://github.com/appleboy/gin-jwt
项目实操

项目目录

goblog on  main [!?] via
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 实战:Go语言项目之利用JWT实现用户认证