3 restframework-认证

3.1APIView 认证:

  • 认证是否已经登陆,如果已经登陆返回元组,如果没有登陆报错
  • 源码流程
  1. 执行dispatch方法:
  2. def dispatch(self, request, *args, **kwargs):
  3. #1.封装request 对原生request进行加工,执行initialize_request方法
  4. request = self.initialize_request(request, *args, **kwargs)
  5. try:
  6. #2.认证
  7. self.initial(request, *args, **kwargs)
  8. #--------------------initialize_request-------------------
  9. #执行initialize_request:
  10. def initialize_request(self, request, *args, **kwargs):
  11. """
  12. Returns the initial request object.
  13. """
  14. parser_context = self.get_parser_context(request)
  15. #返回实例化Request,把原有的request进行封装,丰富功能
  16. return Request(
  17. request,
  18. parsers=self.get_parsers(),
  19. authenticators=self.get_authenticators(),
  20. negotiator=self.get_content_negotiator(),
  21. parser_context=parser_context
  22. )
  23. #---------------------------------------------------------
  24. #--------------------Request------------------------------
  25. #而Request类中:实例化方法中定义:
  26. class Request:
  27. def __init__(self, request, parsers=None, authenticators=None,
  28. negotiator=None, parser_context=None):
  29. assert isinstance(request, HttpRequest), (
  30. 'The `request` argument must be an instance of '
  31. '`django.http.HttpRequest`, not `{}.{}`.'
  32. .format(request.__class__.__module__, request.__class__.__name__)
  33. )
  34. self._request = request#1
  35. self.parsers = parsers or ()
  36. self.authenticators = authenticators or ()#
  37. self.negotiator = negotiator or self._default_negotiator()
  38. self.parser_context = parser_context
  39. self._data = Empty
  40. self._files = Empty
  41. self._full_data = Empty
  42. self._content_type = Empty
  43. self._stream = Empty
  44. #1 : 获取原生request 通过 request._request
  45. #2 : 获取认证类的对象 通过 request.authenticators
  46. #返回dispatch方法中继续走
  47. #---------------------------------------------------------
  48. #--------------------initial----------------------------
  49. #再initial执行方法:
  50. def initial(self, request, *args, **kwargs):
  51. ...
  52. #4.实现认证
  53. self.perform_authentication(request)
  54. #---------------------------------------------------------
  55. #--------------------perform_authentication---------------
  56. #返回当前登陆用户,此时request为封装加工后的request
  57. def perform_authentication(self, request):
  58. request.user
  59. #---------------------------------------------------------
  60. #---------------------------Request----------------------
  61. #执行request为Request类中实例化的对象,通过.user执行user方法
  62. class Request:
  63. ...
  64. @property
  65. def user(self):
  66. if not hasattr(self, '_user'):
  67. with wrap_attributeerrors():
  68. #获取认证对象,进行一步步认证
  69. self._authenticate()
  70. return self._user
  71. #---------------------------------------------------------
  72. #----------------_authenticate-------------------------
  73. def _authenticate(self):
  74. #authentication_classes=[BasicAuthentication对象,]
  75. #authenticators为定义authentication_classes=中的对象
  76. #循环所有认证对象。
  77. for authenticator in self.authenticators:
  78. try:
  79. #通过authenticate方法验证是否登陆,如果登陆返回元组,如果未登陆报错
  80. user_auth_tuple = authenticator.authenticate(self)
  81. except exceptions.APIException:
  82. self._not_authenticated()
  83. raise
  84. if user_auth_tuple is not None:
  85. self._authenticator = authenticator
  86. self.user, self.auth = user_auth_tuple
  87. return
  88. #---------------------------------------------------------
  89. #-------------------------authenticate-----------------------------
  90. def authenticate(self, request):
  91. return (self.force_user, self.force_token)
  • 那么如何自己定义认证:
  1. import json
  2. from django.http import HttpResponse
  3. from django.shortcuts import render
  4. from rest_framework.decorators import authentication_classes#用于自定义实现认证
  5. from rest_framework.views import APIView
  6. from rest_framework import exceptions#用于认证失败引发错误
  7. class MyAuthentication(object):
  8. #重写authenticate方法
  9. def authenticate(self,request):
  10. token = request._request.GET.get('token')
  11. print(token)
  12. if not token:
  13. raise exceptions.AuthenticationFailed("用户认证失败")
  14. return ("hello",None)
  15. def authenticate_header(self,val):pass
  16. class DogView(APIView):
  17. #自定义认证类
  18. authentication_classes = [MyAuthentication,]
  19. def get(self,request,*args,**kwargs):
  20. ret = {
  21. "code":1000,
  22. 'msg':"OK"
  23. }
  24. return HttpResponse(json.dumps(ret),status=200)
  25. def post(self,request,*args,**kwargs):
  26. return HttpResponse("创建Dog")
  27. #www.xxx.com/?token=123
  • 效果:

    • 当访问URL为<http://127.0.0.1:8000/dog/

    • 当访问URL为<http://127.0.0.1:8000/dog/?token=123>

  • 基于认证总结:

    1. 源码流程 dispatch开始

3.2 用户登陆

  • models.py

    1. class UserInfo(models.Model):
    2. user_type_choice = {
    3. (1,"普通用户"),
    4. (2,"VIP"),
    5. (3,"SVIP")
    6. }
    7. user_type = models.IntegerField(choices=user_type_choice)
    8. username = models.CharField(max_length=32,unique=True)
    9. password = models.CharField(max_length=32)
    10. class UserToken(models.Model):
    11. user = models.OneToOneField(to="UserInfo")
    12. token = models.CharField(max_length=32)
  • views.py

  1. def md5(user):
  2. """密码加密"""
  3. import hashlib
  4. import time
  5. ctime = str(time.time())
  6. m = hashlib.md5(bytes(user,encoding='utf-8'))
  7. m.update(bytes(ctime,encoding="utf-8"))
  8. return m.hexdigest()
  9. class AuthView(APIView):
  10. def post(self,request,*args,**kwargs):
  11. ret = {"code":1000,"msg":None}
  12. try:
  13. username = request._request.POST.get('username')
  14. password = request._request.POST.get('password')
  15. obj = models.UserInfo.objects.filter(username=username,password=password).first()
  16. if not obj:
  17. ret["code"] = 1001
  18. ret["msg"] = "用户密码错误"
  19. #为登陆用户创建token
  20. token = md5(username)
  21. #存在更新,不存在创建,保存Token
  22. models.UserToken.objects.update_or_create(user=obj,defaults={"token":token})
  23. except Exception as e:
  24. ret["code"] = 1002
  25. ret["msg"] = "请求异常"
  26. return JsonResponse(ret)

3.3用户登陆实现token认证

  1. #充当数据库数据
  2. ORDER_DICT = {
  3. 1: {
  4. 'name': '媳妇',
  5. 'age': 18,
  6. 'gender': '男',
  7. 'content': '...'
  8. },
  9. 2: {
  10. 'name': '老狗',
  11. 'age': 19,
  12. 'gender': '男',
  13. 'content': '....'
  14. }
  15. }
  16. #自定义认证类
  17. class Authtication(object):
  18. def authenticate(self,request):
  19. token = request._request.GET.get("token")
  20. token_obj = models.UserToken.objects.filter(token=token).first()
  21. #如果token表示用户认证失败
  22. if not token_obj:
  23. raise exceptions.AuthenticationFailed("用户认证失败")
  24. #在restframework内部会将这两个字段赋值给request,以供后续使用
  25. #第一个值通过request.user可以获取
  26. #第二个值通过reuqest.auth可以获取
  27. return (token_obj.user,token_obj)
  28. def authenticate_header(self, val): pass
  29. class OrderView(APIView):
  30. authentication_classes = [Authtication,]
  31. def get(self,request,*args,**kwargs):
  32. # token = request._request.GET.get("token")
  33. # if not token:
  34. # return HttpResponse("用户未登陆")
  35. ret = {"code": 1000, "msg": None, "data": None}
  36. try:
  37. ret['data'] = ORDER_DICT
  38. except Exception as e:
  39. pass
  40. return JsonResponse(ret)
  41. #通过restframework让视图函数只做数据处理,认证交给authentication_classes,代码逻辑清晰不少。

3.4认证流程原理

  • drf认证组件的实现过程:

    1. as_view() --->view --->执行dispatch方法,
    2. 为自己dispatch方法。通过initialize_requestrequest对象进行了重新封装。通过initial执行perform_authenticationRequest执行user方法去执行_authenticate,遍历循环authentication_classes所有对象。执行认证类的方法.
    3. 有三种情况:
    4. 1.如果有返回值,是一个元组 request.user,request.auth
    5. 2.如果返回None,下一个认证来处理:
    6. 当都返回None:request.user = AnonymousUser, request.auth = None
    7. 3.抛出异常,执行self.not_authenticated()
  • 当都返回None, request.user = AnonymousUser, request.auth = None.(设置默认值,表示未登陆)

  • 源码中 全局使用配置项:

    1. 将自己定义认证类配置在rest_framework配置项目中
    2. #当前项目新建文件夹,新建py文件,放入认证类
    3. settings.py配置
    4. REST_FRAMEWORK = {
    5. #全局使用认证类。
    6. 'DEFAULT_AUTHENTICATION_CLASSES':['api.utils.auth.Authtication',],
    7. #设置匿名用户None。
    8. 'UNAUTHENTICATED_USER':None,#request.user = None
    9. 'UNAUTHENTICATED_TOKEN':None,#当前用户未登陆表示匿名用户 request.auth = None
    10. }
    11. #这样类视图都不用加authentication_classes,也可以执行认证。对于不需要认证的类视图,可以添加未 authentication_classes = []

3.5 django内置认证类

  • 如下:5个类:
  1. class BaseAuthentication:
  2. class BasicAuthentication(BaseAuthentication):#通过浏览器生成登陆模态框,实现base64加密,把加密后信息放在请求头发过去。
  3. class SessionAuthentication(BaseAuthentication):
  4. class TokenAuthentication(BaseAuthentication):
  5. class RemoteUserAuthentication(BaseAuthentication):
  • 为了让我们写认证类,更加规范,自定义认证类都必须要继承于BaseAuthentication
  1. class BaseAuthentication:
  2. """
  3. All authentication classes should extend BaseAuthentication.
  4. """
  5. def authenticate(self, request):
  6. """
  7. Authenticate the request and return a two-tuple of (user, token).
  8. """
  9. raise NotImplementedError(".authenticate() must be overridden.")
  10. def authenticate_header(self, request):
  11. #当认证失败时候,浏览器给返回响应头
  12. """
  13. Return a string to be used as the value of the `WWW-Authenticate`
  14. header in a `401 Unauthenticated` response, or `None` if the
  15. authentication scheme should return `403 Permission Denied` responses.
  16. """
  17. pass
  18. #所有定义认证类必须有authenticate,authenticate_header方法。否则无法正常执行代码

Django:RestFramework之-------认证的更多相关文章

  1. Django rest-framework框架-认证组件的简单实例

    第一版 : 自己写函数实现用户认证 #models from django.db import models #用户表 class UserInfo(models.Model): user_type_ ...

  2. django restframework

    一.django restframework 请求流程源码剖析 上面的认证一个流程是rest_framework的关于APIauth的认证流程,,这个流程试用权限.频率.版本.认证.这个四个组件都是通 ...

  3. django restframework jwt

    既然要来学习jwt(json web token),那么我们肯定是先要了解jwt的优势以及应用场景--跨域认证. $ pip install djangorestframework-jwt 传统coo ...

  4. Django Restframework 实践(一)

    具备以下知识: django http://www.cnblogs.com/menkeyi/p/5882464.html http://www.cnblogs.com/menkeyi/p/588245 ...

  5. django restframework 的日常使用

    本文讨论 django restframework 的日常使用,满足常用 api 编写的需求,比如 List, Detail, Update, Put, Patch 等等.探讨 django rest ...

  6. Django RestFramework (DRF)

    准备: 下载 pip install djangorestframework 一 APIView源码解析 1 预备知识 CBV(class based view)FBV(function based ...

  7. django restframework serializer 增加自定义字段

    在使用django restframework serializer 序列化在django中定义的model时,有时候我们需要额外在serializer中增加一些model中没有的字段.有两种方法实现 ...

  8. Django组件之认证系统

      Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Dja ...

  9. Django Rest Framework(认证、权限、限制访问频率)

    阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc

随机推荐

  1. 201871010115——马北《面向对象程序设计JAVA》第二周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  2. 10 使用 OpenCV、Kafka 和 Spark 技术进行视频流分析

    问题引起 基于分布式计算框架Spark的室内防盗预警系统 首先用摄像头录一段视频,存在电脑里,下载一个ffmpeg的软件对视频进行处理,处理成一张张图片,然后通过hadoop里边的一个文件系统叫做hd ...

  3. 网页网站基础入门篇: 使用Adobe Dreamweaver CS6 制作网页/网站

    咱开发网页或者网站呢,最好使用个软件,我使用的是Adobe Dreamweaver CS6 (自行下载安装) 打开软件 现在呢咱使用 html5 <!doctype html> <h ...

  4. 微信小程序 scroll-view 横向滚动条 隐藏无效

    看了许多网上教程说是添加如下样式可以解决,我加入到组件wxss中无效,加入全局wxss生效. 添加css代码如下: ::-webkit-scrollbar { ; ; color: transpare ...

  5. 洛谷 p1047 校门外的树 线段树做法

    非常easy, 注意一下它是两端开始,也就是说0的位置也有一棵树就好了 我由于太弱了,一道红题交了4,5遍 由于树的砍了就没了,lazy标记最大就是1; 直接贴代码吧 #include<bits ...

  6. SQL 变形

    需求:共有协议X份,已签XX份,待签X份 sql: select count(1) 总记录数, sum(case when XY_STATUS='1' then 1 else 0 end)待签, su ...

  7. git 学习网站

    GitBook  :https://git-scm.com/book/zh/v2 Git 教程 廖雪峰 :https://www.liaoxuefeng.com/wiki/89604348802960 ...

  8. csv文件处理

    读取csv文件 import csv with open('demo.csv', 'r') as fp: reader = csv.reader(fp) titles = next(reader) f ...

  9. 课后选做题-MyOD

    课后选做题-MyOD od命令的了解 功能 od命令用于将指定文件内容以八进制.十进制.十六进制.浮点格式或ASCII编码字符方式显示,通常用于显示或查看文件中不能直接显示在终端的字符.od命令系统默 ...

  10. mysql主从复制报错解决方案

    mysql主从复制报错解决方案 我先制造个错误 在slave删除个info3字段 然后在master 在info3插入数据 报错如下<pre> Last_SQL_Errno: 1054 L ...