第1课_JWT应用
热度🔥:24 免费课程
授课语音
JWT 的基本概念与使用场景
JWT(JSON Web Token)是一种轻量级的、跨平台的认证机制。它用于在不同的系统之间传递安全信息,尤其是在基于Web的应用中,广泛应用于用户认证、授权等场景。JWT可以通过加密方式保护数据的完整性和安全性,广泛用于分布式系统中的身份认证。
1. JWT 的基本概念
JWT 是一种用于在网络应用环境间传递声明的 compact 和 URL-safe 的令牌格式。JWT 由三部分组成:
- 头部(Header):通常包含令牌的类型(JWT)和签名算法(如HMAC SHA256或者RSA)。
- 载荷(Payload):包含声明信息(Claims)。JWT的载荷部分是可自定义的,可以包含用户身份、权限等信息。
- 签名(Signature):由头部和载荷部分以及密钥生成,确保JWT的完整性和认证来源。
JWT格式:
Header.Payload.Signature
JWT 的结构图:
- Header:用于声明令牌的类型(通常为JWT)和签名算法(如HMAC SHA256,RSA等)。
- Payload:包含了需要传输的数据(声明)。这些声明是以键值对的形式存储的,可以是公认的注册声明、私有声明等。
- Signature:通过头部指定的算法对头部和载荷进行签名,确保数据的完整性和认证来源。
2. JWT 的使用场景
JWT在现代Web应用中非常常见,主要用于身份验证和授权。以下是JWT的几个典型应用场景:
2.1 用户认证
当用户登录时,系统会验证其身份并生成一个JWT令牌,令牌中包含用户信息和权限。随后用户每次发送请求时都需要携带这个JWT,以证明自己的身份。
- 优点:无需频繁查询数据库或会话存储,提高系统性能。
- 常见应用:登录认证,OAuth2.0认证,单点登录(SSO)等。
2.2 用户授权
JWT可以包含用户的角色和权限信息。在分布式应用中,服务端可以通过解析JWT来验证用户是否有权限执行某些操作。例如,可以在JWT中添加“角色(role)”字段来进行权限管理。
- 优点:可以实现灵活的权限控制,适用于微服务架构中的跨服务权限验证。
- 常见应用:API的权限控制,微服务之间的身份和权限验证等。
2.3 单点登录(SSO)
JWT广泛应用于单点登录(SSO)系统中。在多个服务之间共享用户的认证信息时,使用JWT可以避免在每个服务中都存储用户的认证状态。用户登录后,JWT作为全局认证令牌传递给各个子系统。
- 优点:实现跨多个系统的统一认证,提升用户体验。
- 常见应用:企业内部多个系统的统一登录,第三方授权(如Google、GitHub登录)等。
3. JWT 的工作原理
JWT在认证和授权中通常遵循以下流程:
用户登录: 用户提交用户名和密码,后端服务器验证用户身份。
生成JWT: 一旦用户验证通过,后端生成一个JWT,包含用户信息(如ID、角色等)和有效期。服务器使用密钥对JWT进行签名。
返回JWT: 后端将JWT返回给客户端,客户端将其存储(通常在浏览器的localStorage或sessionStorage中)。
发送请求时携带JWT: 客户端在每次请求时,将JWT作为HTTP请求头(Authorization)的一部分发送给后端。
验证JWT: 后端接收到JWT后,使用密钥对其进行验证,确认JWT没有被篡改,并检查其有效期。
授权操作: 如果JWT有效且权限足够,后端允许客户端执行相应的操作;否则,返回错误信息。
4. JWT 代码实现
4.1 安装依赖
首先,使用Go语言的JWT库来生成和解析JWT。常用的Go语言JWT库是github.com/dgrijalva/jwt-go
。
go get github.com/dgrijalva/jwt-go
4.2 生成 JWT
以下是一个使用Go生成JWT的示例代码:
package main
import (
"fmt"
"time"
"github.com/dgrijalva/jwt-go"
)
// 定义密钥
var mySigningKey = []byte("secret")
// 定义JWT的Claims
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
func generateJWT(username string) (string, error) {
// 设置JWT的有效载荷
claims := MyClaims{
Username: username,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Hour * 72).Unix(), // 设置过期时间为72小时
Issuer: "my-app", // 设置发行者
},
}
// 使用HMAC签名算法生成token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 生成token字符串
tokenString, err := token.SignedString(mySigningKey)
if err != nil {
return "", err
}
return tokenString, nil
}
func main() {
// 生成JWT
tokenString, err := generateJWT("john_doe")
if err != nil {
fmt.Println("生成JWT失败:", err)
return
}
fmt.Println("生成的JWT:", tokenString)
}
4.3 解析 JWT
当用户每次请求时,后端可以使用密钥解析JWT并验证其有效性。以下是解析JWT的代码示例:
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"strings"
)
// 定义密钥
var mySigningKey = []byte("secret")
func parseJWT(tokenString string) (*jwt.Token, error) {
// 解析JWT并验证
token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
// 确保token签名方法是HMAC
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("签名方法不匹配")
}
return mySigningKey, nil
})
if err != nil {
return nil, err
}
return token, nil
}
func main() {
// 假设接收到的JWT
tokenString := "<your-jwt-token-here>"
// 解析JWT
token, err := parseJWT(tokenString)
if err != nil {
fmt.Println("解析JWT失败:", err)
return
}
// 获取JWT中的Claim数据
if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
fmt.Println("Username:", claims.Username)
} else {
fmt.Println("无效的JWT")
}
}
4.4 代码解析
生成JWT:
- 使用
jwt.NewWithClaims
创建一个新的JWT,并指定SigningMethodHS256
作为签名算法。 - 设置JWT的有效期(72小时)和发行者信息。
- 使用
SignedString
方法签名JWT,生成最终的JWT字符串。
- 使用
解析JWT:
- 使用
jwt.ParseWithClaims
方法解析JWT,提供一个验证函数来检查签名是否有效。 - 如果JWT有效,可以通过
token.Claims
获取JWT中的用户信息。
- 使用
5. 总结
通过本课的学习,我们了解了JWT的基本概念、使用场景及其工作原理。JWT广泛应用于用户认证、授权和单点登录等场景。通过Go语言的jwt-go
库,我们能够方便地生成和解析JWT,实现安全可靠的用户身份验证与权限控制。在实际开发中,JWT为我们提供了一个简洁高效的认证解决方案,适用于分布式系统和微服务架构中的身份验证需求。