以Golang的Beego框架为例,添加JWT
1.JWT概述
1)用户登录:
输入用户名和密码。
服务器验证凭据。
若凭据有效,服务器会生成一个JWT,其中包含用户ID、用户名和其他相关信息。
2)JWT的结构:
JWT由三部分组成:头部、载荷和签名。
头部: 包含令牌的类型和所使用的签名算法。
载荷: 包含用户声明,如用户ID、用户名、令牌过期时间等。
签名: 用于验证令牌在传输过程中未被篡改。
3)JWT的使用:
一旦获得了JWT,它就会随每个请求发送到服务器。
服务器接收到JWT后,会验证其签名,确保其有效且未过期。
如果验证通过,服务器会处理请求并返回相应的响应。
4)JWT的优势:
无状态: 由于所有用户信息都包含在令牌中,服务器不需要存储会话信息。
可扩展: 令牌可以在多个服务之间共享,适用于微服务架构。
跨域支持: 令牌可以跨域传输,适用于单页应用(SPA)。
5)潜在问题:
安全问题: 如果JWT被截获,攻击者可以利用它进行未授权访问。
过期管理: 需要妥善处理令牌的过期和刷新机制,以防止未授权访问
2.Beego安装JWT
1 | go get github.com/dgrijalva/jwt-go |
1)封装 JWT,创建一个工具类,用于生成、验证 JWT 等操作
1 | package utils |
secretKey:。
是一个自定义的密钥,可以是任意字符串。这个密钥用于对 JWT 进行签名,以确保其完整性和安全性。签名就是通过密钥和 JWT 的头部与负载生成的,密钥是验证签名的关键。所以,your_secret_key 必须是服务器和客户端都知晓的密钥。虽然可以使用任意字符串,但为了安全,应该避免简单或可预测的密钥。
1)密钥的作用
签名:在生成 JWT 时,密钥用于对 JWT 的头部和负载进行签名,生成签名部分。
验证:在解析 JWT 时,密钥用于验证签名是否正确,确保 JWT 没有被篡改。
2) 密钥的安全性
保密性:密钥必须保密,不能泄露给未经授权的方。如果密钥泄露,攻击者可以伪造 JWT。
复杂性:密钥应足够复杂且随机,避免使用简单的字符串,如 “secret” 或 “password”。
3)密钥的存储
环境变量:推荐将密钥存储在环境变量中,避免直接写在代码中。推荐做法
配置文件:可以将密钥存储在配置文件中,但确保配置文件不在版本控制系统中。
通常,系统中的所有用户会共享同一个 secret_key,这个密钥用于对所有用户的 JWT 进行签名和验证。共享密钥时,需要注意密钥的安全性,避免泄露。可以通过定时任务或外部服务定期更新配置文件中的 JWT 密钥。更新后需重启应用或监听配置文件变化并热加载新密钥。
1 | token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { |
jwt.ParseWithClaims()
首先是对tokenString
进行解析变成3部分:头部、负载和签名。内部函数是个匿名函数,这个函数是ParseWithClaims
的第三参数要求的,职责是提供用于验证 JWT 签名的密钥,token *jwt.Token
就是tokenString
解析后的成果,这个匿名函数返回二进制秘钥,用于验证这个成果中包含的签名部分是否正确,确保 JWT 没有被篡改。
1 | if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { |
这是断言token.Claims
是否CustomClaims
类型数据,即断言tokenString
解析后的负载是否类型正确。ok是个bool值,token.Valid
表示签名验证的结果,也是个bool值。
负载的类型正确,如果签名无效,则说明 JWT 可能在传输过程中被篡改。
2)在 Beego 控制器中,使用中间件的方式来验证用户的身份。
3).用户登录逻辑中,生成 Token 并返回给客户端。
在 Beego 的 router.go
文件中添加一个中间件来拦截所有请求,并验证 Token。
token传回客户端的方式:
1.URL 参数的方式,这种方式简单直观,但安全性较差,因为 token 可能会被记录在服务器日志或浏览器历史中。因此,这种方式虽然可行,但不推荐用于生产环境。
2.使用 Cookie,这比 URL 参数更安全,因为 Cookie 可以设置为 HttpOnly,防止 XSS 攻击。Cookie 还能自动附带在后续请求中,减少了手动管理 token 的复杂性。
在前端页面中,虽然无法通过 JavaScript 访问 HttpOnly Cookie,但浏览器会自动将其附带在后续请求中。
3.使用 HTTP 头部传递 token,这种方式更加安全,因为 token 不会暴露在 URL 或 Cookie 中。客户端需要在每次请求时手动设置 Authorization 头部。