在一家传媒公司做网站编辑 如何,长沙0731手机平台网,一个网站一年多少钱,做淘宝客的网站所需空间Django REST framework JWT一、JWT简介二、JWT 组成headersignature三.使用手动生成jwt前端保存jwt一、JWT简介JWT(Json Web Token) 是一个开放标准(RFC 7519)#xff0c;它定义了一种用于简洁#xff0c;自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT…Django REST framework JWT一、JWT简介二、JWT 组成headersignature三.使用手动生成jwt前端保存jwt一、JWT简介JWT(Json Web Token) 是一个开放标准(RFC 7519)它定义了一种用于简洁自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名。它具备两个特点简洁(Compact)可以通过URL, POST 参数或者在 HTTP header 发送因为数据量小传输速度快自包含(Self-contained)负载中包含了所有用户所需要的信息避免了多次查询数据库二、JWT 组成JWT就一段字符串由三段信息构成的将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品)第三部分是签证(signature).headerjwt的头部承载两部分信息声明类型这里是jwt声明加密的算法 通常直接使用 HMAC SHA256完整的头部就像下面这样的JSON{typ: JWT,alg: HS256}然后将头部进行base64.b64encode()加密(该加密是可以对称解密的),构成了第一部分.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9python中base64加密解密import base64str1 adminstr2 str1.encode()b1 base64.b64encode(str2) #数据越多加密后的字符串越长b2 base64.b64decode(b1) #admin各个语言中都有base64加密解密的功能所以我们jwt为了安全需要配合第三段加密payload载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品这些有效信息可以存放下面三个部分信息。标准中注册的声明公共的声明私有的声明标准中注册的声明 (建议但不强制使用) iss: jwt签发者sub: jwt所面向的用户aud: 接收jwt的一方exp: jwt的过期时间这个过期时间必须要大于签发时间nbf: 定义在什么时间之前该jwt都是不可用的.iat: jwt的签发时间jti: jwt的唯一身份标识主要用来作为一次性token,从而回避重放攻击。以上是JWT 规定的7个官方字段供选用公共的声明 公共的声明可以添加任何的信息一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息因为该部分在客户端可解密.私有的声明 私有声明是提供者和消费者所共同定义的声明一般不建议存放敏感信息因为base64是对称解密的意味着该部分信息可以归类为明文信息。定义一个payloadjson格式的数据:{sub: 1234567890,exp: 3422335555, #时间戳形式name: John Doe,admin: true}然后将其进行base64.b64encode() 加密得到JWT的第二部分。eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9signatureJWT的第三部分是一个签证信息这个签证信息由三部分组成header (base64后的)payload (base64后的)secret密钥这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串然后通过header中声明的加密方式进行加盐secret组合加密然后就构成了jwt的第三部分。// javascriptvar encodedString base64UrlEncode(header) . base64UrlEncode(payload);var signature HMACSHA256(encodedString, secret); //xxxx // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ将这三部分用.连接成一个完整的字符串,构成了最终的jwt:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ注意secret是保存在服务器端的jwt的签发生成也是在服务器端的secret就是用来进行jwt的签发和jwt的验证所以它就是你服务端的私钥在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。jwt的优点1. 实现分布式的单点登陆非常方便2. 数据实际保存在客户端所以我们可以分担都武器的存储压力3. JWT不仅可用于认证还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数jwt的构成非常简单字节占用很小所以它是非常便于传输的。jwt的缺点1. 数据保存在了客户端我们服务端只认jwt不识别客户端。2. jwt可以设置过期时间但是因为数据保存在了客户端所以对于过期时间不好调整。#secret_key轻易不要改一改所有客户端都要重新登录认证流程图首先前端通过Web表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个HTTP POST请求。建议的方式是通过SSL加密的传输(https协议)从而避免敏感信息被嗅探。后端核对用户名和密码成功后将用户的id等其他信息作为JWT Payload(负载)将其与头部分别进行Base64编码拼接后签名形成一个JWT。形成的JWT就是一个形同lll.zzz.xxx的字符串。后端将JWT字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在localStorage或sessionStorage上退出登录时前端删除保存的JWT即可。前端在每次请求时将JWT放入HTTP Header中的Authorization位。(解决XSS和XSRF问题)5.后端检查是否存在如存在验证JWT的有效性。例如检查签名是否正确检查Token是否过期检查Token的接收方是否是自己(可选)。三.使用1.安装pip install djangorestframework-jwt -i https://mirrors.aliyun.com/pypi/simple/2.配置配置https://github.com/jpadilla/django-rest-framework-jwt在settings文件中REST_FRAMEWORK {DEFAULT_AUTHENTICATION_CLASSES: (rest_framework_jwt.authentication.JSONWebTokenAuthentication,rest_framework.authentication.SessionAuthentication,rest_framework.authentication.BasicAuthentication,),}import datetimeJWT_AUTH {JWT_EXPIRATION_DELTA: datetime.timedelta(days1),}JWT_EXPIRATION_DELTA 指明token的有效期手动生成jwtDjango REST framework JWT 扩展的说明文档中提供了手动签发JWT的方法from rest_framework_jwt.settings import api_settingsjwt_payload_handler api_settings.JWT_PAYLOAD_HANDLERjwt_encode_handler api_settings.JWT_ENCODE_HANDLERpayload jwt_payload_handler(user)token jwt_encode_handler(payload)在子应用路由urls.py中from rest_framework_jwt.views import obtain_jwt_tokenurlpatterns [path(rlogin/, obtain_jwt_token),]在主路由中引入当前子应用的路由文件urlpatterns [...path(user/, include(users.urls)),# include 的值必须是 模块名.urls 格式,字符串中间只能出现一个圆点]前端保存jwt我们可以将JWT保存在cookie中也可以保存在浏览器的本地存储里我们保存在浏览器本地存储中浏览器的本地存储提供了sessionStorage 和 localStorage 两种从属于window对象sessionStorage 浏览器关闭即失效localStorage 长期有效使用方法sessionStorage.变量名 变量值 // 保存数据sessionStorage.setItem(变量名,变量值) // 保存数据sessionStorage.变量名 // 读取数据sessionStorage.getItem(变量名) // 读取数据sessionStorage.removeItem(变量名) // 清除单个数据sessionStorage.clear() // 清除所有sessionStorage保存的数据localStorage.变量名 变量值 // 保存数据localStorage.setItem(变量名,变量值) // 保存数据localStorage.变量名 // 读取数据localStorage.getItem(变量名) // 读取数据localStorage.removeItem(变量名) // 清除单个数据localStorage.clear() // 清除所有sessionStorage保存的数据