<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      django restframework框架二 認證

      @(python之路)[django restframework框架二 認證]
      django restframework框架二 認證

      需求分析

      為用戶訪問時,顯示用戶未登錄

      原始方法

      urls.py

      from django.conf.urls import url,include
      urlpatterns = [
          url(r'^api/(?P<version>\w+)', include("app01.urls")),
      ]
      
      

      app01.urls.py

      from django.conf.urls import url
      from app01 import views
      urlpatterns = [
          url(r'user/$', views.UserView.as_view()),
          # url(r'^auth/$', views.UserView.as_view()),
      ]
      

      views.py

      from django.shortcuts import render,HttpResponse
      from rest_framework.views import APIView
      from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
      
      class UserView(APIView):
      
          def get(self,request,*args,**kwargs):
              token = request.query_params.get("token")
              if not token:
                  return HttpResponse("未認證")
              print(request.version)
      
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      
      

      利用rest framework方法去做

      from django.shortcuts import render,HttpResponse
      from rest_framework.views import APIView
      from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
      
      from rest_framework.authentication import BaseAuthentication
      from rest_framework.exceptions import AuthenticationFailed
      
      class MyAuthtication(BaseAuthentication):
          def authenticate(self, request):
              token = request.query_params.get("token")
              if not token:
                   raise AuthenticationFailed("認證失敗")   
              return ("小公子","www.xxxx.com")
      
      class UserView(APIView):
          authentication_classes = [MyAuthtication,]
          def get(self,request,*args,**kwargs):
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      

      源碼分析

      ?我們已經知道,認證是封裝在了新的reqeust里邊了。忘記點我

      def initialize_request(self, request, *args, **kwargs):
          parser_context = self.get_parser_context(request)
      
          return Request(
              request,
              parsers=self.get_parsers(),
              authenticators=self.get_authenticators(),  [MyAuthtication,]對象
              negotiator=self.get_content_negotiator(),
              parser_context=parser_context
          )
      

      我們可以看看認證具體做了什么authenticators
      1

      def get_authenticators(self):
      
          return [auth() for auth in self.authentication_classes]
      

      2
      self.authentication_classes實例化所有的認證

      
      class APIView(View):
      	……
      	authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
      	……
      

      我們主要關注的是這里。當我們在自己的views.py中定義好了,他就會優先查找views.py中的了。
      3
      我們關注一下這個認證傳遞到了哪里了

      def initialize_request(self, request, *args, **kwargs):
      
          parser_context = self.get_parser_context(request)
      
          return Request(
              request,
              parsers=self.get_parsers(),
              authenticators=self.get_authenticators(),
              negotiator=self.get_content_negotiator(),
              parser_context=parser_context
          )
      

      從上邊我們知道,他首先封裝到了request里邊了,傳入的地方在這里

      class Request(object):
         
          def __init__(self, request, parsers=None, authenticators=None,
                       negotiator=None, parser_context=None):
              assert isinstance(request, HttpRequest), (
                  'The `request` argument must be an instance of '
                  '`django.http.HttpRequest`, not `{}.{}`.'
                  .format(request.__class__.__module__, request.__class__.__name__)
              )
      
              self._request = request
              self.parsers = parsers or ()
              self.authenticators = authenticators or ()     ####### 就是這里[MyAuthentcators]
              self.negotiator = negotiator or self._default_negotiator()
              self.parser_context = parser_context
              self._data = Empty
              self._files = Empty
              self._full_data = Empty
              self._content_type = Empty
              self._stream = Empty
      

      上述只是認證的封裝真正的處理在這里dispatch

      def dispatch(self, request, *args, **kwargs):
      
          self.args = args
          self.kwargs = kwargs
          request = self.initialize_request(request, *args, **kwargs)
          self.request = request
          self.headers = self.default_response_headers  # deprecate?
      
          try:
              self.initial(request, *args, **kwargs)
      
             
              if request.method.lower() in self.http_method_names:
                  handler = getattr(self, request.method.lower(),
                                    self.http_method_not_allowed)
              else:
                  handler = self.http_method_not_allowed
      
              response = handler(request, *args, **kwargs)
      
          except Exception as exc:
              response = self.handle_exception(exc)
      
          self.response = self.finalize_response(request, response,
      
      

      這些處理都在self.initial(request, *args, **kwargs)這里

      def initial(self, request, *args, **kwargs):
           self.format_kwarg = self.get_format_suffix(**kwargs)
      
      
           neg = self.perform_content_negotiation(request)
           request.accepted_renderer, request.accepted_media_type = neg
      
          
           version, scheme = self.determine_version(request, *args, **kwargs)
           request.version, request.versioning_scheme = version, scheme
      
           # Ensure that the incoming request is permitted
           # 處理認證
           self.perform_authentication(request)
           self.check_permissions(request)
           self.check_throttles(request)
      

      self.perform_authentication(request)

          def perform_authentication(self, request):
              request.user
      

      我們猜測request.user會觸發認證對象列表。他們應該回有關系。
      僅僅猜測是不好使的我們需要證明

      def user(self):
      
          if not hasattr(self, '_user'):
              with wrap_attributeerrors():
                  self._authenticate()
          return self._user
      

      因為沒有hasattr(self, '_user'):所以他會走

      def _authenticate(self):
          for authenticator in self.authenticators:
              try:
                  user_auth_tuple = authenticator.authenticate(self)
              except exceptions.APIException:
                  self._not_authenticated()
                  raise
      
              if user_auth_tuple is not None:
                  self._authenticator = authenticator
                  self.user, self.auth = user_auth_tuple
                  return
      
          self._not_authenticated()
      

      我們需要關注的是self.authenticators

      class Request(object):
      
          def __init__(self, request, parsers=None, authenticators=None,
                       negotiator=None, parser_context=None):
              assert isinstance(request, HttpRequest), (
                  'The `request` argument must be an instance of '
                  '`django.http.HttpRequest`, not `{}.{}`.'
                  .format(request.__class__.__module__, request.__class__.__name__)
              )
      
              self._request = request
              self.parsers = parsers or ()
              self.authenticators = authenticators or ()
              self.negotiator = negotiator or self._default_negotiator()
              self.parser_context = parser_context
              self._data = Empty
              self._files = Empty
              self._full_data = Empty
              self._content_type = Empty
              self._stream = Empty
      
              if self.parser_context is None:
                  self.parser_context = {}
              self.parser_context['request'] = self
              self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET
      
              force_user = getattr(request, '_force_auth_user', None)
              force_token = getattr(request, '_force_auth_token', None)
              if force_user is not None or force_token is not None:
                  forced_auth = ForcedAuthentication(force_user, force_token)
                  self.authenticators = (forced_auth,)
      
      

      他就是原來的self.authenticators,也就是說我們自己的[MyAuthtion對象,]
      所以他會循環我們的[MyAuthtion對象,],所以 user_auth_tuple = authenticator.authenticate(self)這里就會返回一個元組。下面捕獲異常,
      為什么元組返回兩個元組

      def _authenticate(self):
              for authenticator in self.authenticators:
                  try:
                      user_auth_tuple = authenticator.authenticate(self)
                  except exceptions.APIException:
                      self._not_authenticated()
                      raise
      
                  if user_auth_tuple is not None:
                      self._authenticator = authenticator
                      self.user, self.auth = user_auth_tuple
                      return
      
              self._not_authenticated()
      

      ?返回后一個給self.user,一個給self.auth。
      所以,返回有三種情況。
      第一種:
      raise AuthenticationFailed("認證失敗")
      拋出異常,認證失敗
      第二種:
      return ("xiaogozi",'123123')
      返回元組,認證成功
      第三種:
      返回None
      匿名用戶登陸
      ?如果不是not Noneself._authenticator = authenticator

      def _not_authenticated(self):
      
          self._authenticator = None
      	# 如果我們配置UNAUTHENTICATED_USER;就會執行
      	# self.user
          if api_settings.UNAUTHENTICATED_USER:
              self.user = api_settings.UNAUTHENTICATED_USER()
          else:
              self.user = None
      	# 如果我們配置UNAUTHENTICATED_TOKEN
      	# 就會執行self.auth
          if api_settings.UNAUTHENTICATED_TOKEN:
              self.auth = api_settings.UNAUTHENTICATED_TOKEN()
          else:
              self.auth = None
      

      settings.py添加

      REST_FRAMEWORK = {
          "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
          "ALLOWED_VERSIONS":["v1","v2"],
          "UNAUTHENTICATED_USER":None,   # 允許用戶匿名登陸
          "UNAUTHENTICATED_TOKEN":None,   # 
      }
      

      也可以這樣寫

          "UNAUTHENTICATED_USER":lambda:None,   # 允許用戶匿名登陸
          "UNAUTHENTICATED_TOKEN":lambda:None,   # 
      

      推薦用第一種方式

      ?當我們自己寫的MyAuthtication返回(user,auth)的時候,我們認為認證成功,
      并將元組分別賦值給request.user/request.auth;
      ?raise AuthenticationFailed("認證失敗") 此時認證失??;
      ?返回None,表示匿名用戶。

      認證與數據庫關聯

      我們返回的是用戶和認證信息,這種信息我們最好寫在數據庫中;

      整理:
      urls.py

      
      from django.conf.urls import url
      from app01 import views
      urlpatterns = [
          url(r'user/$', views.UserView.as_view()),
          url(r'auth/$', views.Auth.as_view()),
          # url(r'^auth/$', views.UserView.as_view()),
      ]
      
      

      views.py

      from django.shortcuts import render,HttpResponse
      from django.http import JsonResponse
      
      from rest_framework.views import APIView
      from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
      
      from rest_framework.authentication import BaseAuthentication
      from rest_framework.exceptions import AuthenticationFailed
      from app01 import models
      class MyAuthtication(BaseAuthentication):
          def authenticate(self, request):
              token = request.query_params.get("token")
              if not token:
                  raise AuthenticationFailed("認證失敗")
              return ("小公子","www.xxxx.com")
      
      
      
      class UserView(APIView):
          authentication_classes = [MyAuthtication,]
          def get(self,request,*args,**kwargs):
              self.dispatch
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      
      class Auth(APIView):
          def post(self,request,*args,**kwargs):
              response = {"code":1000}
              user = request.data.get("username")
              pwd = request.data.get("password")
              obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
              if not obj:
                  response["code"] = 1001
                  response["msg"] = "用戶名密碼錯誤"
                  return JsonResponse(responsejson_dumps_params={"ensure_ascii":False})
              import uuid
              token = str(uuid.uuid4())
              models.UserInfo.objects.update_or_create(user=obj,defaults={"token":token})
              response["token"] = token
              return JsonResponse(responsejson_dumps_params={"ensure_ascii":False})
      

      models.py

      from django.db import models
      class UserInfo(models.Model):
          username = models.CharField(max_length=32)
          password = models.CharField(max_length=64)
      
      class UserToken(models.Model):
          user = models.OneToOneField("UserInfo")
          token = models.CharField(max_length=64)
      

      或者:
      我們把認證這里拿出來,形成 一個單獨的文件例如:在app01下新建一個目錄utils。

      from rest_framework.authentication import BaseAuthentication
      from rest_framework.exceptions import AuthenticationFailed
      from app01 import models
      
      class TokenAuthtication(BaseAuthentication):
          def authenticate(self, request):
              """
      
              :param request:
              :return:
                  (user,auth) 表示認證成功,并將元組分別復制給request.user/request.auth
                   raise AuthenticationFailed('認證失敗') 表示認證失敗
                   None, 表示匿名用戶
              """
              token = request.query_params.get('token')
              if not token:
                  raise AuthenticationFailed('用戶Token未攜帶')
      
              token_obj = models.UserToken.objects.filter(token=token).first()
              if not token_obj:
                  raise AuthenticationFailed('token已失效或錯誤')
              return (token_obj.user.username,token_obj)
      
      

      只需要在settings.py添加一行;

      
      REST_FRAMEWORK = {
          'DEFAULT_AUTHENTICATION_CLASSES':['app01.utils.auth.TokenAuthtication',]
      }
      
      

      這樣就將驗證添加到全局,訪問所有都需要token認證;
      如果有的頁面不需要我們只需要在那個類下添加:

      class AuthView(APIView):
          authentication_classes = []
          ……
      

      這樣這個AuthView就不需要驗證。

      補充

      class MyAuthtication(BaseAuthentication):
      	pass
      

      我們繼承的是BaseAuthentication

      
      class BaseAuthentication(object):
          def authenticate(self, request):
              raise NotImplementedError(".authenticate() must be overridden.")
          # 如果認證失敗可以返回響應頭;
          def authenticate_header(self, request):
              pass
      

      其他方式認證

      class CSRFCheck(CsrfViewMiddleware)
      class BasicAuthentication(BaseAuthentication):
      class SessionAuthentication(BaseAuthentication):
      class TokenAuthentication(BaseAuthentication)
      class RemoteUserAuthentication(BaseAuthentication)
      
      posted @ 2018-06-01 14:26  zz小公子  閱讀(222)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 公安县| 国产成人片无码视频| 又粗又硬又黄a级毛片| 日韩精品一区二区三区视频| jk白丝喷浆| 亚洲国产精品一二三四区| 国产在线精品欧美日韩电影| 国产无码高清视频不卡| 91精品一区二区蜜桃| 日本夜爽爽一区二区三区| 在线人成免费视频69国产| 中文字幕av日韩有码| 色综合视频一区二区三区| 丁香五月婷激情综合第九色 | 高清无码爆乳潮喷在线观看| 国产成人高清亚洲综合| 丰满人妻被黑人猛烈进入| 国产成人精品亚洲日本片| 国产视色精品亚洲一区二区| 老鸭窝在线视频| 久久精品国产九一九九九| 欧美国产日产一区二区| 日日躁夜夜躁狠狠躁超碰97| 日本一区二区三区视频版| 国产成人精彩在线视频| 克什克腾旗| 天堂a无码a无线孕交| 国产精品免费观看色悠悠| 国产免费一区二区不卡| 国产粉嫩美女一区二区三| 欧美肥老太交视频免费| 亚洲av不卡电影在线网址最新| 蜜臀av午夜精品福利| 亚洲精品国产福利一区二区| 亚洲an日韩专区在线| 真实国产老熟女无套内射| 久久精品亚洲精品国产色婷| 国内自拍偷拍福利视频看看| 国产精品不卡区一区二| 女同另类激情在线三区| 人妻中文字幕在线视频无码|