【2022-10-12】DRF从入门到入土(十)

cookie,session,token

参考博客链接:https://www.cnblogs.com/liuqingzheng/p/8990027.html

drf之jwt认证原理介绍

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


# 构成和工作原理
	JWT就是一段字符串,由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

	# header:头
    	-声明类型,这里是jwt
	    -声明加密的算法 通常直接使用 HMAC SHA256
        -公司信息由
        {
          'typ': 'JWT',
          'alg': 'HS256'
        }
        变成了(base64的编码)
        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    # payload:荷载
        exp: jwt的过期时间,这个过期时间必须要大于签发时间
        iat: jwt的签发时间
        用户信息: 用户信息由
        {
          "exp": "1234567890",
          "name": "John Doe",
          "userid": 3
        }
       变成了(base64的编码)
       eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
        
    # signature:签名
    	把头和荷载加密后得到的:TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
        
        
        
    #注意:secret是保存在服务器端的(加密方式+盐),jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了
    
    
    
    
 # jwt使用流程最核心的是:
	-签发:登录接口签发
    -认证:认证类认证# Json web token (JWT), token的应用于web方向的称之为jwt

base64编码和解码

# base64 可以把字符串编码成base64的编码格式:(大小写字母,数字和 =)eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9

# base64可以把base64编码的字符串,解码回原来的格式

# 应用场景:
	- jwt中使用
    - 网络中传输字符串就可以使用base64编码
    - 网络中传输图片,也可能使用base64的编码
    
    
# 编码解码
# 把图片保存起来看看
import json
import base64
d = {'name': 'lqz', 'userid': 6, 'age': 19}
info = json.dumps(d)
print(info)
# 把字符串使用base64编码
res=base64.b64encode(info.encode('utf-8'))
print(res)  # eyJuYW1lIjogImxxeiIsICJ1c2VyaWQiOiA2LCAiYWdlIjogMTl9


res=base64.b64decode(s)
with open('code.png','wb') as f:
    f.write(res)

drf之jwt认证快速使用

# jwt:签发(登录接口) 认证(认证类)
# django中使用jwt
    https://github.com/jpadilla/django-rest-framework-jwt  (旧版本)
    https://github.com/jazzband/djangorestframework-simplejwt (新版本)
  
    
# 安装
	pip3 install djangorestframework-jwt
# 快速使用
	-直接迁移表,因为它默认使用auth的user表签发token
    	makemigrations  migrate
    -创建超级用户(auth的user表中要右记录)
    	createsuperuser
    -这样我们就不需要写登录接口了,如果是使用auth的user表作为用户表,它可以快速签发
    -签发(登录):只需要在路由中配置(因为它帮咱们写好登录接口了)
    
    from rest_framework_jwt.views import obtain_jwt_token
    urlpatterns = [
        path('login/', obtain_jwt_token),
    ]
    
    -认证(认证类):先导入,然后配置在视图类上
    	class TestView(APIView):
            authentication_classes = [JSONWebTokenAuthentication,]
            permission_classes = [IsAuthenticated,]
            
    -前端访问时,token需要放在请求头中
    	Authorization:jwt token串
    

drf之jwt修改返回格式

# 登录成功后,前端看到的格式是固定的,只有token,我们想做成如下格式
	{code:100,msg:'登录成功',token:adfasdfasdf}
    
    
# 有个固定写法:写一个函数,函数返回什么,前端就看到什么,配置在配置文件中

# 使用步骤:
	1 写一个函数
    def jwt_response_payload_handler(token, user=None, request=None):
        return {
            'code':100,
            'msg':'登录成功',
            'username':user.username,
            'token':token
        }
     2 把函数配置在配置文件中
        JWT_AUTH={
        'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.response.jwt_response_payload_handler',
    	}
        
 # 以后登录接口返回的格式就是咱们写的函数的返回值

集群的概念

集群是一组相互独立的、通过高速计算机网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理。一个客户与集群相互作用时,集群像是一个独立的服务器。

计算机集群简称集群是一种计算机系统, 它通过一组松散集成的计算机软件/硬件连接起来高度紧密地协作完成计算工作。在某种意义上,他们可以被看作是一台计算机。集群系统中的单个计算机通常称为节点,通常通过局域网连接,但也有其它的可能连接方式。集群计算机通常用来改进单个计算机的计算速度和/或可靠性。一般情况下集群计算机比单个计算机,比如工作站或超级计算机性能价格比要高得多。

分布式概念

要理解分布式系统,主要需要明白一下2个方面:

1.分布式系统一定是由多个节点组成的系统。其中,节点指的是计算机服务器,而且这些节点一般不是孤立的,而是互通的。

2.这些连通的节点上部署了我们的节点,并且相互的操作会有协同。

不同的业务模块部署在不同的服务器上或者同一个业务模块分拆多个子业务,部署在不同的服务器上,解决高并发的问题,提供可扩展性以及高可用性,业务中使用分布式的场景主要有分布式存储以及分布式计算。分布式存储中可以将数据分片到多个节点上,不仅可以提高性能(可扩展性),同时也可以使用多个节点对同一份数据进行备份。


分布式环境的特点



分布性:服务部署空间具有多样性
并发性:程序运行过程中,并发性操作是很常见的。比如同一个分布式系统中的多个节点,同时访问一个共享资源。数据库、分布式存储
无序性:进程之间的消息通信,会出现顺序不一致问题


分布式环境下面临的问题



网络通信:网络本身的不可靠性,因此会涉及到一些网络通信问题
网络分区(脑裂):当网络发生异常导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式架构的所有节点,只有部分节点能够正常通信
三态:在分布式架构里面多了个状态:超时,所以有三态: 成功、失败、超时
分布式事务:ACID(原子性、一致性、隔离性、持久性)
中心化和去中心化:冷备或者热备

集群和分布式的区别

集群与分布式区别

集群:复制模式,每台机器做一样的事。

分布式:两台机器分工合作,每台机器做的不一样。

X_FORWARDED_FOR 的概念

通过名字就知道,X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。

X-Forwarded-For 请求头格式非常简单,如下:
	X-Forwarded-For: client, proxy1, proxy2

自主练习

快速签发,修改返回格式,自定义用户表,签发token

urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', obtain_jwt_token),
    path('user/', views.UserAuth.as_view()),
    path('user/login/', views.UserView.as_view())
]

models.py

from django.db import models


# Create your models here.


class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    email = models.EmailField(max_length=32)
    phone = models.CharField(max_length=32)
    address = models.CharField(max_length=64)

views.py

from rest_framework.views import APIView
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .models import User


class UserAuth(APIView):
    authentication_classes = [JSONWebTokenAuthentication, ]  # 使用jwt提供的认证类,必须配合权限类使用
    permission_classes = [IsAuthenticated, ]

    def get(self, request):
        return Response('您已登录成功')


from rest_framework.exceptions import APIException
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


class UserView(APIView):
    def post(self, request):
        try:
            username = request.data.get('username')
            password = request.data.get('password')
            email = request.data.get('email')
            phone = request.data.get('phone')
            address = request.data.get('address')
            user = User.objects.get(username=username, password=password, phone=phone, email=email, address=address)
            payload = jwt_payload_handler(user)  # 根据user签发token,使用django_rest_framework_jwt提供的签发token方法生成token
            token = jwt_encode_handler(payload)

            return Response({'code': 200,
                             'msg': '登录成功',
                             'username': username,
                             'phone': phone,
                             'email': email,
                             'token': token})
        except Exception as a:
            raise APIException('用户名或密码错误')

change.py

def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'code': 200,
        'msg': '登录成功',
        'username': user.username,
        'token': token
    }

settings.py

JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.change.jwt_response_payload_handler',
}

测试

自定义认证类,验证token

auth.py

from rest_framework.authentication import BaseAuthentication
import jwt
from rest_framework.exceptions import AuthenticationFailed
from .models import User
from rest_framework_jwt.settings import api_settings

jwt_decode_handler = api_settings.JWT_DECODE_HANDLER


class UserAuthentication(BaseAuthentication):
    def authenticate(self, request):
        user_value = request.META.get('HTTP_TOKEN')

        try:
            payload = jwt_decode_handler(user_value)
        except jwt.ExpiredSignature:
            msg = 'token签名过期'
            raise AuthenticationFailed(msg)
        except jwt.DecodeError:
            msg = 'token签名解码失败'
            raise AuthenticationFailed(msg)
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('未知错误')

        user = User.objects.filter(pk=payload['user_id']).first()

        return (user, user_value)

posted @   dy12138  阅读(110)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示