DRF JWT认证(一)

DRF JWT认证(一)

DRF JWT认证(一)

JWT认证

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

Json web token (JWT),token是一种认证机制,用在web开发方向,叫JWT

为什么使用JWT 认证?

我们想记录用户注册或者登录后的状态,或者创建身份认证的凭证,可以使用Session认证机制,或者我们现在所要说的JWT 认证机制,那么为什么有了Session认证机制还要使用JWT??

Session机制

DRF JWT认证(一)

DRF JWT认证(一)

JWT机制

DRF JWT认证(一)

DRF JWT认证(一)

图解后,可知如果登录用户很多,需要在后端存很多数据,频繁查询数据库,导致效率低,JWT就可以使我们可以不在服务端存数据,又够保证数据安全,在客户端存数据 —-> token认证机制

下面我们了解一下JWT的构成和工作原理

构成和工作原理

JWT的构成

JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用 .进行连接形成最终传输的字符串。比如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JWT头是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存

第一段头部承载的信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

完整的头部就像下面这样的JSON:

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

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

2. payload

第二段是载荷,载荷就是存放有效信息的地方,是JWT的主体内容部分,也是一个 JSON对象,承载的信息:

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

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

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.

  • iat: jwt的签发时间

  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避时序攻击。

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

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

除以上标准注册声明字段外,我们还可以自定义字段, 一般会把包含用户信息的数据放到payload中,如下例:

{
  "sub": "1234567890",
  "name": "HammerZe",
  "admin": true
}

注意:虽然说用户信息数据可以存放到payload中,但是默认情况下JWT是未加密的,Base64算法也只是编码并不会提供安全的加密算法,一般程序员拿到Base64编码的字符串都可以解码出内容,所以不要存隐私信息,比如密码,防止泄露,存一些非敏感信息

3. signature

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

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

简单来说,第三段是签证信息,由三部分组成:

[En]

To put it simply, the third paragraph is visa information, which consists of three parts:

  • header (base64后的)
  • payload (base64后的)
  • secret

这个部分需要base64加密后的header和base64加密后的payload使用 .连接组成的字符串,然后通过header中声明的加密方式进行加盐 secret组合加密,然后就构成了JWT的第三部分。

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

关于签发和核验JWT,我们可以使用Django REST framework JWT扩展来完成。

总结

注意JWT每部分的作用,在服务端接收到客户端发送过来的JWT token之后:

header和payload可以直接利用base64解码出原文,从header中获取哈希签名的算法,从payload中获取有效数据

signature由于使用了不可逆的加密算法,无法解码出原文,它的作用是校验token有没有被篡改。服务端获取header中的加密算法之后,利用该算法加上secretKey对header、payload进行加密,比对加密后的数据和客户端发送过来的是否一致。注意secretKey只能保存在服务端,而且对于不同的加密算法其含义有所不同,一般对于MD5类型的摘要加密算法,secretKey实际上代表的是盐值

本质原理

JWT认证算法:签发与校验

"""
1)jwt分三段式:头.体.签名 (head.payload.sgin)
2)头和体是可逆加密,让服务器可以反解出user对象;签名是不可逆加密,保证整个token的安全性的
3)头体签名三部分,都是采用json格式的字符串,进行加密,可逆加密一般采用base64算法,不可逆加密一般采用hash(md5)算法
4)头中的内容是基本信息:公司信息、项目组信息、token采用的加密方式信息
{
    "company": "公司信息",
    ...

}
5)体中的内容是关键信息:用户主键、用户名、签发时客户端信息(设备号、地址)、过期时间
{
    "user_id": 1,
    ...

}
6)签名中的内容时安全信息:头的加密结果 + 体的加密结果 + 服务器不对外公开的安全码 进行md5加密
{
    "head": "头的加密字符串",
    "payload": "体的加密字符串",
    "secret_key": "安全码"
}
"""

签发:根据登录请求提交来的 账号 + 密码 + 设备信息 签发 token

"""
1)用基本信息存储json字典,采用base64算法加密得到 头字符串
2)用关键信息存储json字典,采用base64算法加密得到 体字符串
3)用头、体加密字符串再加安全码信息存储json字典,采用hash md5算法加密得到 签名字符串

账号密码就能根据User表得到user对象,形成的三段字符串用 . 拼接成token返回给前台
"""

校验:根据客户端带token的请求 反解出 user 对象

"""
1)将token按 . 拆分为三段字符串,第一段 头加密字符串 一般不需要做任何处理
2)第二段 体加密字符串,要反解出用户主键,通过主键从User表中就能得到登录用户,过期时间和设备信息都是安全信息,确保token没过期,且时同一设备来的
3)再用 第一段 + 第二段 + 服务器安全码 不可逆md5加密,与第三段 签名字符串 进行碰撞校验,通过后才能代表第二段校验得到的user对象就是合法的登录用户
"""

JWT的种类

其实JWT(JSON Web Token)指的是一种规范,这种规范允许我们使用JWT在两个组织之间传递安全可靠的信息,JWT的具体实现可以分为以下几种:

  • nonsecure JWT:未经过签名,不安全的JWT
  • JWS:经过签名的JWT
  • JWEpayload部分经过加密的JWT

nonsecure JWT

未经过签名,不安全的JWT。其 header部分没有指定签名算法

{
  "alg": "none",
  "typ": "JWT"
}

并且也没有 Signature部分

JWS

JWS ,也就是JWT Signature,其结构就是在之前nonsecure JWT的基础上,在头部声明签名算法,并在最后添加上签名。 创建签名,是保证jwt不能被他人随意篡改。我们通常使用的JWT一般都是JWS

为了完成签名,除了用到header信息和payload信息外,还需要算法的密钥,也就是 secretKey。加密的算法一般有2类:

  • 对称加密: secretKey指加密密钥,可以生成签名与验签
  • 非对称加密: secretKey指私钥,只用来生成签名,不能用来验签(验签用的是公钥)

JWT的密钥或者密钥对,一般统一称为JSON Web Key,也就是 JWK

到目前为止,jwt的签名算法有三种:

  • HMAC【哈希消息验证码(对称)】:HS256/HS384/HS512
  • RSASSA【RSA签名算法(非对称)】(RS256/RS384/RS512)
  • ECDSA【椭圆曲线数据签名算法(非对称)】(ES256/ES384/ES512)

base64编码与解码

import base64
import json

dic_info={
  "sub": "1234567890",
  "name": "HammerZe",
  "admin": True
}

'''base64编码'''
必须是bytes类型
s = json.dumps(dic_info).encode('utf8')
enbase64_str = base64.b64encode(s)
print(enbase64_str)
b'eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9'

'''base64解码'''
en_res = b'eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9'

debase64_str = base64.b64decode(en_res).decode('utf8')
print(base64.b64decode(en_res),type(base64.b64decode(en_res)))
b'{"sub": "1234567890", "name": "HammerZe", "admin": true}'
print(debase64_str)
{"sub": "1234567890", "name": "HammerZe", "admin": true}

注意

  • *base64长度必须是4的倍速,如果不够就使用 = 补齐,

哪些情景需求base64?建议参考下博文

为什么要使用base64编码,有哪些情景需求? – 知乎 (zhihu.com)

Original: https://www.cnblogs.com/48xz/p/16123916.html
Author: HammerZe
Title: DRF JWT认证(一)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/500034/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Torch和Numpy的高级索引,即,方括号中还有一个Tensor或Numpy

    最近看代码,看到了一个Tensor的方括号中还有一个Tensor,给爷看懵了。 new_embeddings = new_token_embeddings[input_flags]…

    Python 2023年8月25日
    053
  • python自定义cmap_Python matplotlib的使用并自定义colormap的方法

    0.前言 添加colormap的对象是灰度图,可以变成热量图,从而更加明显的发现一些规律,适用于一些雷达图像等 from PIL import Image 将彩色图片转换成黑白图片…

    Python 2023年9月4日
    050
  • 深度学习笔记:07神经网络之手写数字识别的经典实现

    神经网络之手写数字识别的经典实现 上一节完成了简单神经网络代码的实现,下面我们将进行最终的实现:输入一张手写图片后,网络输出该图片对应的数字。由于网络需要用0-9一共十个数字中挑选…

    Python 2023年8月28日
    056
  • Django简介

    Django项目:项目文件夹下有一个同名目录以及一个manage.py文件 同名目录: __init__.py : 空文件,指定当前目录可作为包使用 settings.py : 是…

    Python 2023年8月5日
    051
  • pandas 排序和排名

    Series和DataFrame可以按照索引进行排序,也可以按照值来排序,对值也可以进行排名。 一,按照索引排序(sort by index) 对于一个Series或DataFra…

    Python 2023年8月21日
    048
  • flask+nginx+uwsgi部署服务器(详细保姆级教程)

    从零开始部署flask项目 概要 准备工作 * 服务器 Xshell Xftp 7 部署flask * 方案选择 python3安装 安装uwsgi 安装nginx nginx和u…

    Python 2023年8月10日
    082
  • 手把手教你做项目web框架flask篇——基础用法详解

    目录 导读 为什么用flask 安装flask 启动flask flask里name的用处 转换器和变量规则 重定向 设置错误页面 json数据读取 cookie和session …

    Python 2023年8月9日
    040
  • 第5章 pandas入门

    整述:pandas是有使数据清洗和分析工作变得更快更简单的数据结构和操作工具。pandas经常和其它工具⼀同使用,如数值计算工具NumPy和SciPy,分析库statsmodels…

    Python 2023年8月6日
    061
  • ChatGPT保姆级注册教程

    啊哦~你想找的内容离你而去了哦 内容不存在,可能为如下原因导致: ① 内容还在审核中 ② 内容以前存在,但是由于不符合新 的规定而被删除 ③ 内容地址错误 ④ 作者删除了内容。 可…

    Python 2023年11月4日
    041
  • 错误集合_20220131

    此部分内容主要是工作中遇到的一些报错,简单的解决方案会直接贴出来,链接一般为问题解决方案详细解释。 shell脚本写得一切正常,但是一执行就报错:line: XXX “…

    Python 2023年8月10日
    038
  • matplotlib绘制一行三列图(通常用做文献图片)

    使用matplotlib绘制一种经常在文献中出现的并列折线图。 附代码,并且来会单独说明一些绘制困难的点。 目录 效果图 绘图代码 1 数据元组 2.子图位置subplot设置 3…

    Python 2023年9月6日
    052
  • 数据分析一、 pandas库基础知识

    pandas库基础知识 一、jupyter 代码编辑器 概述:Python 数据分析库介绍 二、pandas 库基础知识 * (1)常用的Series属性与方法: (2) Data…

    Python 2023年8月6日
    053
  • 【Python码住雪景小程序】雪景人像最强攻略:让你一下美10倍、美醉了(中国人不骗中国人)

    导语 哈喽~大家早上好鸭! 冷空气来袭,不少地方一夜入冬,南方地区除了冷就是雨,而北方除了冷还有 雪⛄。 就说下雪这件事吧,其实南北都特别期待。诗意的白色世界、戏剧般的氛围,容易让…

    Python 2023年9月20日
    060
  • 07#Web 实战:实现 GitHub 个人主页项目拖拽排序

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 弹尽粮绝,会员救园:…

    Python 2023年10月14日
    032
  • Squarespace 和 WordPress 的区别

    💂 个人网站:【海拥 】【摸鱼游戏 】【神级源码资源网站 】 🤟 前端学习课程:👉【28个案例趣学前端 】【400个JS面试题 】 💅 想寻找共同学习交流、摸鱼划水的小伙伴,请点击…

    Python 2023年11月5日
    051
  • 什么是动态规划?

    什么是动态规划? 今天简单说一下动态规划的定义以及简单示例。动态规划,是一种将原问题分解成简单的子问题来解决复杂问题的思想。 其中,动态规划还具有最优子结构性质和子问题重叠性质。 …

    Python 2023年6月11日
    064
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球