首页 > 其他 > 详细

Django REST framework之认证组件实例以及源码流程分析

时间:2019-08-02 22:27:12      阅读:102      评论:0      收藏:0      [点我收藏+]

基于用户传入的token进行认证

需求:对于一些api需要用户登录成功之后才能访问,有些api又不需要登录就能访问

解决思路:   a:创建两张表

      b.用户来访问的时候带上服务器发给用户token值

1.创建models.py

 1 from django.db import models
 2 
 3 
 4 class UserInfo(models.Model):
 5     user_choices_type = (
 6         (1, 普通用户),
 7         (2, vip用户),
 8         (3, svip用户),
 9     )
10     user_type = models.IntegerField(choices=user_choices_type)
11     username = models.CharField(max_length=32, unique=True)
12     password = models.CharField(max_length=64)
13 
14 
15 class UserToken(models.Model):
16     user = models.OneToOneField(to=UserInfo, on_delete=models.CASCADE)
17     token = models.CharField(max_length=64)

2.urls.py

1 urlpatterns = [
2     re_path(api/v1/auth/$, views.AuthView.as_view()),
3     re_path(api/v1/order/$, views.OrderView.as_view()),
4 ]

3.认证类

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from rest_framework.authentication import BaseAuthentication
 5 from rest_framework.exceptions import AuthenticationFailed
 6 from api import models
 7 
 8 
 9 class Authticate(BaseAuthentication):
10 
11     def authenticate(self, request):
12         token = request._request.GET.get(token)
13         token_obj = models.UserToken.objects.filter(token=token).first()
14         if not token_obj:
15             raise AuthenticationFailed(用户认证失败)
16         return (token_obj.user, token_obj)
17 
18     def authenticate_header(self, request):
19         """
20         认证失败之后返回给浏览器响应头
21         :param request:
22         :return:
23         """
24         pass

4.views.py 

 1 from django.http import JsonResponse
 2 from rest_framework.views import APIView
 3 from api import models
 4 
 5 
 6 order_dict = {
 7     1: {
 8         name: 拉皮条,
 9         age: 18,
10         gengder: ,
11         content: 买了个充气的
12     },
13     2: {
14         name: 热狗,
15         age: 18,
16         gengder: ,
17         content: 买了个非酋
18     }
19 }
20 
21 
22 def md5(user):
23     import hashlib
24     import time
25     ctime = str(time.time())
26     m = hashlib.md5(user.encode(utf8))
27     m.update(ctime.encode(utf8))
28     return m.hexdigest()
29 
30 
31 class AuthView(APIView):
32     """
33     登录相关的逻辑
34     """
35     authentication_classes = []
36     def post(self, request, *args, **kwargs):
37 
38         ret = {code: 1000, msg: None, token: None}
39         try:
40             user = request._request.POST.get(username)
41             pwd = request._request.POST.get(password)
42             obj = models.UserInfo.objects.filter(username=user, password=pwd).first()
43             if not obj:
44                 ret[code] = 1001
45                 ret[msg] = 用户名或者密码错误
46             # 为登录用户创建token
47             token = md5(user)
48             models.UserToken.objects.update_or_create(user=obj, defaults={token: token})
49             ret[token] = token
50         except Exception as e:
51             ret[code] = 1002
52             ret[msg] = 请求异常
53 
54         return JsonResponse(ret)
55 
56 
57 class OrderView(APIView):
58     """
59     订单相关业务
60     """
61 
62     def get(self, request, *args, **kwargs):
63         print(request.user, request.auth)
64         ret = {code: 2000, msg: None, data: None}
65         try:
66             ret[data] = order_dict
67         except Exception as e:
68             ret[code] = 2001
69             ret[msg] = 请求异常
70         return JsonResponse(ret)

5.settings.py

1 REST_FRAMEWORK = {
2     DEFAULT_AUTHENTICATION_CLASSES: [api.utils.auth.Authticate, ],
3     # ‘DEFAULT_AUTHENTICATION_CLASSES‘: [],  # AnonymousUser None配置文件中有
4     # ‘UNAUTHENTICATED_USER‘: lambda: ‘匿名用户‘,
5     # ‘UNAUTHENTICATED_USER‘: None,
6     # ‘UNAUTHENTICATED_TOKEN‘: None,
7 }

总结:实现的思路就是每次用户登录的时候,需要带上token值,如果没有带就获取不到相应的资源,如果登录成功就给用户创建token值,并且给用户返回,若第二次用户登录就给用户更新,同时也返回给用户,当然用户没登录成功就给用户返回相关的错误信息。

认证组件的源码流程分析

 请求进来先找自己的dispatch方法,然而没有,就走父类的APIView,发现有dispatch方法 ,执行self.initialize_request方法,封装Request,之前还有解析器-->执行self.get_authenticators()-->[auth() for auth in self.authentication_classes]列表式生成一个个认证对象--->authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES默认去配置文件中,若自己有,执行initial(self, request, *args, **kwargs)方法---->执行self.perform_authentication(request)------>request.user这是个静态属性----->self._authenticate()---->_authenticate(self)---->authenticator.authenticate(self)---->返回必须是一个元组。

_authenticate(self):循环认证类的所有对象,执行认证类的authenticate方法,1.如果authenticate方法抛异常,执行self._not_authenticated()2.有返回值必须是元组(request.user,request.auth)3.如果返回None,进入下一个认证对象处理,如果全部都是None跳出循环,执行_not_authenticated(self)方法去配置文件了if api_settings.UNAUTHENTICATED_USER就是匿名用户AnonymousUser,否则是slef.user=None,self.auth = api_settings.UNAUTHENTICATED_TOKEN()为None否则self.auth=None。

内置认证类

BaseAuthentication

我们写认证类的时候,必须继承它实现authenticate方法不写直接抛错,authenticate_header这个方法是认证失败给用户返回的响应头信息401认证不通过,也是必须写的方法,但是一般不做什么处理。

BasicAuthentication

这个类大概是通过浏览器把用户的密码和用户名通过base64加密之后发给服务端。

SessionAuthentication

通过django的session做的认证。

TokenAuthentication

其实跟我哪个认证token差不多。

RemoteUserAuthentication

这个类是通过认证http请求头。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

      

Django REST framework之认证组件实例以及源码流程分析

原文:https://www.cnblogs.com/Alexephor/p/11285272.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!