jwt的介绍与构成,签发与认证以及使用

一 jwt介绍和构成

集群:写的项目部署在一台机器上称为单节点的部署,而部署在两台三台机器上就是集群
做会话保持的发展历史:详情见:https://www.cnblogs.com/liuqingzheng/p/8990027.html

1.1 JWT认证(Json Web Token:web方向的token认证方案)

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

  • 在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。
    我们不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制
  • Json web token (JWT)原理:JWT用在咱们前后端做登录认证的,如果登录了,就携带token过来,如果没登录,就不携带--->后端通过验证token的准确性,确定是谁访问我们



1.2 JWT的构成——三部分

  • jwt是token的一种,jwt本质就是token
  • jwt 不在服务端存储 (session在服务端存储)
  • JWT就是一段字符串,由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
  • 头部:header
    • 一般放公司信息,声明加密算法(没放秘钥),通常直接使用 HMAC SHA256
      完整的头部就像下面这样的json:
  • 荷载:payload
    • 当前用户的信息:用户名,用户id,token过期时间exp,token签发时间iat
  • 签名:signature
    • 第一部分和第二部分通过某种加密方式+秘钥得到的字符串
    • 使用它,做到防篡改,防伪造

1.3 jwt签发与认证

以后使用jwt,最核心的就是写两个地方:签发和认证

  • 签发(登录接口)
    1 用户携带用户名,密码到后端
    2 校验用户名密码是否正确,如果正确
    3 签发token,按照jwt逻辑生成三段,返回给前端
* 登录接口,登录成功,签发token(三段式)
    * header,用base64编码,暂放
      ```python
      {"company": "公司信息",}
      ```
    * payload,用base64编码,暂放
      ```python
      {用户名,用户权限,过期时间}
      ```
    * 使用加密方式加密:可以使用md5,把header和payload 都update进md5中--->生成摘要,生成签名--->再用base64编码 
    * 三段拼接起来--->用 .分割 
  • 认证(认证类)
    1 用户访问我们需要登录的接口
    2 携带token过来--》请求头,请求地址。。
    3 后端验证用户携带的token,是否被篡改,是否是伪造的,如果没问题
    4 认证通过,继续后续的逻辑
  * 用户携带token过来,认证
  * 取出第一部分 header
  * 取出第二部分 payload
  * 使用之前同样的加密算法(密码),得到新签名
  * 跟token的第三部分比较,如果一样,表示没有被窜改,顺利继续往下走,返回两个值,如果被篡改了,抛异常

1.4 base64编码和解码

base64是编码解码方式,不是加密方式

  • 作用,用途
    1 用在jwt中,token串使用base64编码
    2 互联网中前后端数据交互,可以使用base64编码
    -百度登录:密码先加密---》使用base64编码---》向后端发送
    3 图片二进制可以使用base64编码传递,eg:12306
点击查看代码
img='iVBORw0KGgoAAAANSUhEUgAAAMcAAADHCAIAAAAiZ9CRAAAHDUlEQVR42u3dUZraMAxF4dn/pukGpkB0j+Qoc/IIBSf2n6Jc+Wt/Xh4e9PHjFHh0qfrJjl++9/9/5tKn3nz80hCXXrl0yd/MxrsFKF3FpbGoJfh+WlSlKlWpaqOq2oxcuhLqrdoK1daDGv2IRQrc99+jKlWpSlWrVVHlC/UWXnL1rTT11iVVl4pdqtxUlapUpSpVhQVEuPahM3ZCWyvI2hfiQ6hKVapSlaqoVayNRQUBYb58ZO3xJVCVqlSlKlWFz9JUv5lamAGUk/UinhrgSYeqVKUqVe1VleyqydNbX7nPK4kEVfmKqnxlkSrqqD2u4xuJ8Ey8Lz4I61eqoQ4zUJWqVKWqPaomH3RDVeEUU7uXakOEyQs14X19BVWpSlWq2quq7wG1tpxU+EsVapNl0MBYTZWxqlSlKlUtUhV2YQfaqPh64M1gvPuOF7JUK/rb/VWqUpWqVLVKVS0I6GOBj05lH5SzWmWDJzhsvKIqValKVU9VRcXcYYRNVRJ9IQiFaTI1QE5eVapSlapWqwqnL2yj9sXlVDP4rI+wCAuX6ePoqlKVqlS1URVliNqZhFcS1Dzie5WoG4BNyWsbBVSlKlWp6mGqqJOjmsHU4g10CPBecl/vf7quUpWqVKWq06qofBnfh4RvNsK7sEn9Ad42fcl+va5SlapUpaoNqo6c02SlVcup++rFvrsFH6twQ6pKVapS1TNU1U4OT8CTB91Xwz+pE/KiuFMtEPZWV5WqVKWqRapqz/Zh7N6XEVDZx0AVFRapYShDzc/vdZWqVKUqVe1UFT634/uHwqQjxDTZFR44Z+qty3WVqlSlKlXdWNXZVBpvaePr2nezhRkBPlYS3KhKVapS1SJV+G853oqmnFF0+oJvCmXYn0gmSlWqUpWqNqoKH+knn4HxLUo49zC+HxirqQ2vKlWpSlUbVQ20fik6VB5BrWtfOYWPFU74x9FVpSpVqeoZqqgf9UJE+5r9x/vwrWB93IvlTsliYepUpSpVqephqvqeyfsKLOrjA/EBPtZAywGoq1SlKlWp6rQqKrnGK5K+pIOqNgae7Qdy/LDqVZWqVKWqvarC5+1wHvHUPixfBlLyvp1kAz37j6ehKlWpSlUbVYXtxoGCJiwF8Lfwk5/M8Wsf//iFqlKVqlS1SBWVU+NVVF9NQF1pTXlYV4Vj9R2qUpWqVLVOVV+7sQ8TNdd4yB7KmxwrbLG37FlQlapUpaoNqqgEnNogRfVu+57/qTIIH4udQ1WpSlWqeoYqqtoY6C5TdQNVbRzxQcU9SamtKlWpSlWLVOERNpUj4GvWt+vobEZAjYUsrqpUpSpVPUNVuAx4z5Uq+CarqHDP0xHKSWmrKlWpSlWLVF06KDphahAe1Fz3ZR/UjIXNjMJkqkpVqlLVIlXhjzo1NQNdakoDdQNQjV5qrHAIValKVap6kqqwNKEe4MNlCO8WvK6iogG2HqKmV1WqUpWqFqmqXW2NxQAmPByvFY4hlL6QPbwhv62rVKUqValqlaqw7KAuAC/CwnXtS7cnY/djdZWqVKUqVW1QRf3eh/lyKHggEcC3VZ39VEu2ripVqUpVG1T1rQfec6WKHqpr3rQwr4b/WGusX6IqValKVatV4Y/rR5yFuUYYsofRfEgHHx2oq1SlKlWpaqeqsDQJVR15YMbzd/xuwevO2vSqSlWqUtUDVIWLh+fmlLwXfQzE3H2hQ/c5q0pVqlLVIlX4jzH+g32poMGLwjCVpnoGk/VZ8reAqlSlKlWtVtUXag8UWGGc0ReF48k+XkX11lWqUpWqVHU/VVRuHjZ68VQabwbfNu8OB6XWQlWqUpWqHqkKj4yplvbAMlC3Fl75hV2Npj66qlSlKlUtUoWfLhUf1L4ZX87QfThRfdUqleB8yNZVpSpVqerGqvrqDzzhDWfkSCsab7rj4KiPq0pVqlLVOlVhSfHKDnwVj5QmVAObqimPJBSqUpWqVLVXFfV4PPYTDpZT1KRTnWy8S00tyserUJWqVKWqjarCb8cfs8NIPdx6RVVaOEpqmfB7TFWqUpWq1qmift3xXDhcj4Embq3+oPrxYTMjjHK+7S6rSlWqUtWNVVHlC/UTHjaVqUKN2jsVXik+VndXQ1WqUpWqNqrC+8ThHPWVFAOt377iqe8tpEOvKlWpSlWLVFGVRJi/h4/9Ia++U8Vr0/AtJD54d5mqUpWqVLVQ1cBjP9VCHigBqWqDKrkGxkKqTFWpSlWqWq0KL4zwh/xwavCKre/a+3J8KltXlapUpSpVHckaaiff94fxlu1koYbcmapSlapU9ZdVXQp/w0/11ShhzE0VjtQ3DyylqlSlKlU9QBU+I1Ts3hc6UEVPX8TfN9ZQXaUqValKVTdWhaeuk/UHNfrk9qybWGQ7BKpSlapUtUiVhwd4qMqDP/4BHop8v8NmzwQAAAAASUVORK5CYII='
import json
import base64

base64 的编码和解码(字符串)
编码
d={'name':'lqz','age':19}
d_str=json.dumps(d)
res=base64.b64encode(d_str.encode('utf-8'))  # 字符串转bytes格式
# print(res)  # eyJuYW1lIjogImxxeiIsICJhZ2UiOiAxOX0=
**base64编码字符串长度必须是4的倍数,如果不足,用= 补齐,= 一定不会超过3个**

解码
res1=base64.b64decode('eyJuYW1lIjogImxxeiIsICJhZ2UiOiAxOX0=')
print(res1)  # {'name':'lqz','age':19}

#把图片保存到本地
res=base64.b64decode(img)
with open('xx.png','wb') as f:
    f.write(res)
  • base64特点:
    -大小写数字组合,有时候,结尾会带 =
    -base64编码后的字符串,一定是4个倍数,如果不足,用 = 补齐
    -base64解码可能会出错,不足4的倍数为,我们自己使用=补齐,所以,最多补3个=

二 drf-jwt使用(django 中使用jwt)

可以自己写,也可以使用第三方

2.1 老的:django-rest-framework-jwt

2.1.1 django-rest-framework-jwt快速使用

签发:默认使用auth的user表签发--->登录接口--->人家已经帮我们写好了

    from rest_framework_jwt.views import obtain_jwt_token # 这就是个登录接口,人家帮你写好了
    urlpatterns = [
        path('login/', obtain_jwt_token),
    ]

认证--->认证类

  • 视图类上,配置认证类和权限类才有登录认证
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class BookListView(generics.ListAPIView):
    """
    返回所有图书信息.
    """
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 登录之后才能访问--->但是现在变成了不携带token也能访问,因此我们需要一个权限类
    authentication_classes = [JSONWebTokenAuthentication]
    # 默认认证类,带了token过来,就会校验,不带就不会校验--->不校验 request.user就没有值,使用权限类做限制
    permission_classes = [IsAuthenticated]	 # 登录用户有权限,不登录用户就没有权限  
登录之后才能访问,需要一个登录类和认证类
  • postman测试时
    • 请求头中的key值叫Authorization
    • 请求头中的value值是: jwt 有效的token值

2.1.2 定制签发返回格式

如果是基于auth的user表签发token,就可以不自己写了,但是登录接口返回的格式,只有token,不符合公司规范,所以我们也可以自定义认证返回结果

使用步骤

  • 写个函数
  • 配置一下,项目配置文件
# 新建utils文件写一个定制返回格式的函数
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'status': 100,
        'msg': '登录成功',
        'token': token,
        'username': user.username
    }

# 配置文件配置
JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',
}

2.1.3 源码分析——路由配置后,会有个登录接口的原因

from rest_framework_jwt.views import obtain_jwt_token
path('login/', obtain_jwt_token),
    
obtain_jwt_token 本质是ObtainJSONWebToken.as_view()

本质是ObtainJSONWebToken:
class ObtainJSONWebToken(JSONWebTokenAPIView):
    serializer_class = JSONWebTokenSerializer
    
向login发送post请求,ObtainJSONWebToken一定有个post方法
post方法在父类中:JSONWebTokenAPIView
-登录走的是JSONWebTokenAPIView的post,签发token 是在序列化类中
-签发完token执行了,咱们写的jwt_response_payload_handler,所以才能定制返回格式

2.2 新的:djangorestframework-simplejwt

  • 下载:pip3 install djangorestframework-simplejwt

写登录--》人家帮咱们写了--》用户表-->用的auth的user表
认证类--》人家帮咱们写了

2.2.1 使用步骤

  1. 在应用中注册
  2. 创建用户
  3. 路由层中:
from rest_framework_simplejwt.views import token_obtain_pair
urlpatterns = [
  # 登录接口
    path('login/', token_obtain_pair),
]

这样就完成快速签发token了

posted @ 2023-09-11 22:35  瓜瓜不甜  阅读(139)  评论(0)    收藏  举报