JWT(JSON Web Token)

最近在复习,所以又去学习了一遍这个,之前只是直接拿来用了,所以这次学习还是学到挺多。

目录

什么是JWT?

1、基于session认证 

session认证流程:

基于Session认证所显露的问题:

2、基于Token认证

基于token认证流程:

基于token认证的优点:

缺点:

JWT介绍

JWT的认证流程:

JWT使用

1、什么时候应该使用JWT?

2、JWT结构

1)header

2)payload

3)signature

3、JWT的使用

为什么要使用JWT(JWT的优点)

使用注意事项(安全)

引用:


什么是JWT?

JSON Web Token (JWT) 是一个开放标准 (RFC 7519 ),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为 JSON 对象。此信息可以验证和信任,因为它是数字签名的。JWT 可以使用密钥(使用HMAC算法)或使用RSAECDSA的公钥/私钥对进行签名。

上面是JWT的官方解释,官网地址JSON Web Tokens - jwt.io

而在我学习一些后通俗些讲,JWT(JSON Web Token)就是基于token认证的代表,是一种最常见的token生成的方式。

在此,就想来讨论一下基于token认证。而谈到了基于token认证,就不得不也提到在这之前的基于session 认证。

(本人是直接使用前者,所以对基于session认证了解甚少,正好学习一下)

1、基于session认证 

HTTP是无状态的协议(对于事物处理没有记忆能力,每次客户端与服务端会话完成时,服务端不会保存任何会话信息) ,每次请求都是完全独立,服务端无法确认当前访问者的身份信息,也无法辨别上一次和这一次是否为同一对象。所以服务器与浏览器为了进行会话跟踪,就必须要去维护一个状态,这个状态会告诉服务端前后两个请求是否来自同一浏览器,这个状态就需要cookie和session去实现。

session是基于cookie实现的,cookie通过在客户端记录信息确定用户身份,session通过在服务器端记录信息确定用户身份。session存储在服务器端,sessionId会被存储到户端的cookie中。

session认证流程:

用户认证成功后,在服务端生成用户相关的数据保存在session中(当前会话),而发给客户端的sesssion_id 存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户的合法校验。当用户登出或过期时把服务端session销毁,客户端的session_id也就无效了。

而通过对于cookie和session的展开了解,会发些一些基于session的弊端。

基于Session认证所显露的问题:

  1. cookie是不可跨域的:每个cookie都会绑定单一的域名,无法在别的域名下使用,一级域名和二级域名之间是允许共享使用的(通过domain),由于基于cookie,所以session认证也无法跨域,对单点登录不适用。(单点登录(SSO):在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。)
  2. 服务器压力大:通常session是存储在内存中的,每个用户通过认证之后都会将session数据保存在服务器的内存中,而当用户量增大时,服务器的压力增大。

  3. session共享:现在很多应用都是分布式集群,需要我们做额外的操作进行session共享;

  4. CSRF跨站伪造请求攻击:session机制是基于浏览器端的cookie的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。并且如果浏览器禁用了cookie,这种方式会失效。

  5. 对于非浏览器的客户端,手机移动端等不适用,因为session依赖于cookie,而移动端经常没有cookie。

  6. 前后端分离系统中更加不适用,后端部署复杂,前端发送的请求往往经过多个中间件到达后端,cookie中关于session的信息会转发多次

2、基于Token认证

Token, 令牌,代表执行某些操作的权利的对象。

基于token认证流程:

  1. 客户端使用用户名和密码请求登录
  2. 服务端收到请求,去验证用户名和密码
  3. 验证成功后,服务端会签发一个token,再把这个token返回给客户端
  4. 客户端收到token后可以把它存储起来,比如放到cookie或者Local Storage中
  5. 客户端每次向服务端请求资源时需要携带服务端签发的token,可以在cookie或者header中携带
  6. 服务端收到请求,然后去验证客户端请求里面带着的token,如果验证成功,就向客户端返回请求数据

在HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。localStorage理论上来说是永久有效的,即不主动清空的话就不会消失,即使保存的数据超出了浏览器所规定的大小,也不会把旧数据清空而只会报错。

这种基于token的认证方式相比传统的session认证方式更节约服务器资源,并且对移动端和分布式更加友好。其优点如下。

基于token认证的优点:

  1. 支持跨域访问:cookie无法跨域。将token置于请求头中可以解决这问题。
  2. 无状态化:服务端无需存储token,token自身包含了所有登录的用户信息,只需要验证token信息是否正确即可,这样一来可以减轻服务器压力。
  3. 避免CSRF跨站伪造攻击:由于不再依赖cookie,所以采用token认证方式不会发生CSRF。
  4. 更适用于移动端(Android,iOS,小程序等等):客户端是非浏览器平台时,cookie不被支持。
  5. 无需绑定到一个特殊的身份验证方案(传统的用户名密码登录),只需要生成的token是符合我们预期设定的即可;
  6. 更适用CDN:可以通过内容分发网络请求服务端的所有资料。

缺点:

  1. 相比较于传统的session登陆机制实现起来略微复杂一点
  2. 由于服务器不保存 token,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 token 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

而JWT就是上述的token的一种具体实现方式。

JWT介绍

通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT Token,并且这个JWT Token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。

JWT的认证流程:

  1. 首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探
  2. 后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
  3. 后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可
  4. 前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)
  5. 后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等
  6. 验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果

JWT使用

1、什么时候应该使用JWT?

  • 授权:这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小并且能够在不同的域中轻松使用。

  • 信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。因为可以对 JWT 进行签名(例如,使用公钥/私钥对),所以您可以确定发件人就是他们所说的那个人。此外,由于使用标头和有效负载计算签名,您还可以验证内容没有被篡改。

2、JWT结构

将这三段信息文本用.链接一起就构成了JWT字符串:

头部(header) + 载荷(payload) + 签证(signature)

因此,JWT通常为:xxxxx.yyyyy.zzzzz

1)header

JWT头部承载着两部分信息

  • 声明类型,这里是JWT

  • 声明加密的算法,通常直接使用 HMAC SHA256(写为HS256)

定义一个header:

{
  'typ': 'JWT',
  'alg': 'HS256'
}

然后,这个 JSON 被Base64Url编码以形成 JWT 的第一部分。

2)payload

载荷就是存放有效信息的地方。

  • 标准中注册的声明。这些是一组预定义的声明,它们不是强制性的,但建议使用,以提供一组有用的、可互操作的声明。

  • 公共的声明。这些可以由使用 JWT 的人随意定义。但为避免冲突,它们应在IANA JSON Web 令牌注册表中定义或定义为包含抗冲突命名空间的 URI。

  • 私有的声明。这些是为在同意使用它们的各方之间共享信息而创建的自定义声明,既不是注册声明也不是公共声明。

标准中注册的声明(建议但不强制使用):

  • iss:jwt签发者

  • sub:jwt所面向的用户

  • aud:接收jwt的一方

  • exp:jwt的过期时间,这个过期时间必须要大于签发时间

  • nbf:定义在什么时间之前,该jwt都是不可用的

  • iat:jwt的签发时间

  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而会比重放攻击

公共的声明:

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密

私有的声明:

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息

定义一个payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后对有效负载进行Base64Url编码以形成 JSON Web 令牌的第二部分。

对于已签名的令牌,此信息虽然受到保护以防篡改,但任何人都可以读取。除非已加密,否则请勿将机密信息放入 JWT 的有效负载或标头元素中。JWT只是适合在网络中传输一些非敏感的信息

3)signature

签名哈希部分是对上面两部分数据签名,需要使用base64编码后的header和payload数据,通过指定的算法生成哈希,以确保数据不会被篡改。首先,需要指定一个密钥(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用header中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名

例如,使用 HMAC SHA256 算法,签名将通过以下方式创建:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用.分隔,就构成整个JWT对象

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,他就是你服务端的私钥,在任何场景都不应该泄露出去,一旦客户得知这个secret,那就意味着客户端是可以自我签发jwt了。

3、JWT的使用

该如何应用到java中已经网上已经有很多示例了,在这我就不多搬运了。

为什么要使用JWT(JWT的优点)

  • 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。

  • 因为有了playload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。

  • 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。

  • 它不需要在服务端保存会话信息,所以他易于应用的扩展。

  • 简洁JWT Token数据量小,传输速度也很快

  • 单点登录友好:使用Session进行身份认证的话,由于cookie无法跨域,难以实现单点登录。但是,使用token进行认证的话, token可以被保存在客户端的任意位置的内存中,不一定是cookie,所以不依赖cookie,不会存在这些问题

使用注意事项(安全)

  • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
  • 由于缺乏安全性,也不应该在浏览器存储中存储敏感的会话数据。
  • 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。

  • secret就是你服务端的私钥,在任何场景都不应该泄露出去,一旦客户得知这个secret,那就意味着客户端是可以自我签发jwt了。
  • 每当用户想要访问受保护的路由或资源时,用户代理应该发送 JWT,通常在Authorization标头中使用Bearer模式。标头的内容应如下所示:

    Authorization: Bearer <token

        如果令牌在Authorization标头中发送,则跨域资源共享 (CORS) 不会成为问题,因为它不使用 cookie。

  • 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。(或者是对JWT在前后端之间进行加密之后在传输)。
  • JWT的哈希签名的密钥是存放在服务端的,所以只要服务器不被攻破,理论上JWT是安全的。因此要保证服务器的安全
  • JWT可以使用暴力穷举来破解,所以为了应对这种破解方式,可以定期更换服务端的哈希签名密钥(相当于盐值)。这样可以保证等破解结果出来了,你的密钥也已经换了

引用:

基于session认证

JWT详解

Cookie、Session之登录认证

基于token的登录验证机制

localStorage使用总结

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的基于 JSON Web TokenJWT)的身份验证案例: 1. 安装所需的库 ``` pip install pyjwt ``` 2. 生成JWT Token ```python import jwt import datetime # 定义过期时间 expire_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=30) # 定义payload payload = { 'user_id': '123456', 'username': 'john', 'exp': expire_time } # 生成token jwt_token = jwt.encode(payload, 'secret_key', algorithm='HS256') print(jwt_token) ``` 上述代码中,我们使用了 pyjwt 库来生成 JWT Token。它的 encode() 方法接收三个参数:payload、密钥和算法。payload 是一个字典,包含我们想要在 Token 中存储的信息,例如用户ID、用户名、过期时间等等。密钥是一个字符串,用于加密 Token。算法是指用于加密 Token 的算法,这里我们选择了 HS256。 3. 验证JWT Token ```python import jwt # 定义Token jwt_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzNDU2IiwidXNlcm5hbWUiOiJqb2huIiwiZXhwIjoxNjMxMzEwMDUzfQ.XsDEjcd7jH8qC-6pZlWjZaFvDz-pT8NvQYrWb8I3-5c' # 验证Token try: decoded_token = jwt.decode(jwt_token, 'secret_key', algorithms=['HS256']) print(decoded_token) except jwt.ExpiredSignatureError: print('Token已过期') except jwt.InvalidTokenError: print('无效的Token') ``` 上述代码中,我们使用了 pyjwt 库的 decode() 方法来验证 Token。它接收三个参数:Token、密钥和算法。如果 Token 有效,则返回包含信息的字典。如果 Token 过期或无效,则会引发 jwt.ExpiredSignatureError 或 jwt.InvalidTokenError 异常。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值