JWT详解
一、JWT认证原理
JWT(Json Web Token)是一种服务端向客户端发放令牌的认证方式。客户端用户名密码登录时,服务端会生成一个令牌返回给客户端;客户端随后在向服务端请求时只需携带这个令牌,服务端通过校验令牌来验证是否是来自合法的客户端,进而决定是否向客户端返回应答。
简单来说,就是服务器认证之后,会返回(生成)一个JSON对象,发送给客户端(用户),就像下面一样:
{
"姓名": "张三",
"角色": "管理员",
"到期时间": "2023.10.2"
}
以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。
- 适用场景
授权:
这是最常见的使用场景,解决单点登录问题。因为JWT使用起来轻便,开销小,服务端不用记录用户状态信息(无状态),所以使用比较广泛;
信息交换:
JWT是在各个服务之间安全传输信息的好方法。因为JWT可以签名,例如,使用公钥/私钥对儿 - 可以确定请求方是合法的。此外,由于使用标头和有效负载计算签名,还可以验证内容是否未被篡改。
- 工作流程
1.浏览器发起请求登陆,携带用户名和密码;
2.服务端验证身份,根据算法,将用户标识符打包生成 token,
3.服务器返回JWT信息给浏览器,JWT不包含敏感信息;
4.浏览器发起请求获取用户资料,把刚刚拿到的 token一起发送给服务器;
5.服务器发现数据中有 token,验明正身;
6.服务器返回该用户的用户资料;
二、JWT结构
JWT包含三部分:头部Header、负载Payload和签名Signature。
- 头部Header
头部描述JWT的元数据,包括算法alg和类别typ等信息。alg描述签名算法,这样接收者可以根据对应的算法来验证签名,默认是如下所示的HS256,表示 HMAC-SHA256;typ表示令牌类型,设置为JWT,表示这是一个JWT类型的令牌。 { "alg": "HS256", "typ": "JWT" }
- 负载Payload
存放令牌的主体内容,由认证服务AuthN生成相关信息并放到令牌的负载中。重要属性包括: iss:令牌发行者 issuer aud:令牌受众 audience 在JWT验证时,会校验发行者、受众信息和令牌负载中的发行者iss、受众audience是否匹配。JWT的内容本身不是加密的,所有拿到令牌的服务都可以看到令牌负载Payload中的内容,因此建议Payload里不要存放私密的信息。
- 签名Signature
签名字段是对头部和负载的签名,确保只有特定合法的认证服务才可以发行令牌。实际使用中一般是把头部和负载分别执行Base64转换成字符串,然后使用认证服务的密钥对拼接的字符串进行签名,签名算法正是前面介绍的头域中定义的算法。
一个完整的JWT示例如下:
对于头部Header和负载Payload进行签名得到Signature。
# Header:
{
"alg": "RS512",
"typ": "JWT"
}
# Payload
{
"iss": "weather@cloudnative-istio",
"audience": "weather@cloudnative-istio"
}
# Signature
RSASHA512
(
base64UrlEncode(header) + "." +
base64UrlEncode(payload)
)
以上结构最终输出的令牌如下,可以看到“.”分割的三个字符串分别对应JWT结构的头部、负载和签名三部分。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ2ODU5ODk3MDAsInZlciI6IjIuMCIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoid2VhdGhlckBjbG91ZG5hdGl2ZS1pc3Rpby5ib29rIiwic3ViIjoid2VhdGhlckBjbG91ZG5hdGl2ZS1pc3Rpby5ib29rIn0.SEp-8qiMwI45BuBgQPH-wTHvOYxcE_jPI0wqOxEpauw
三、JWT的优缺点
1、JWT默认不加密,但可以加密。生成原始令牌后,可以使用改令牌再次对其进行加密。
2、当JWT未加密方法是,一些私密数据无法通过JWT传输。
3、JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
4、JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
5、JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
6、为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。