• django DRF认证组件


     
    

    一、学习DRF的认证类; 设计:LoginView不登录就可以访问,UserView和OrderView需要通过认证后才能访问;

    1、urls.py

    1. urlpatterns = [
    2. path('login/', views.LoginView.as_view()),
    3. path('user/', views.UserView.as_view()),
    4. path('order/', views.OrderView.as_view()),
    5. ]

    2、views.py

    1. from rest_framework.authentication import BaseAuthentication
    2. from rest_framework.exceptions import AuthenticationFailed # 认证失败抛出异常使用
    3. class MyAuthentication(BaseAuthentication):
    4. def authenticate(self, request):
    5. '''
    6. 重写这个方法,去做认证,
    7. 1、读取用户请求传递的token;
    8. 2、校验合法性;
    9. 3、返回值:
    10. - 返回一个元组(),认证成功:必须有2个元素,request.user request.auth
    11. - 认证失败,抛出异常,返回错误信息;
    12. - 返回None,在有多个认证类的时候,会依次认证; 都没有认证成功的话,默认为匿名用户;
    13. '''
    14. token = request.query_params.get("token")
    15. if token:
    16. return ("wupeiqi","123456")
    17. else:
    18. raise AuthenticationFailed("认证失败")
    19. class LoginView(APIView):
    20. def get(self,request):
    21. return Response("LoginView")
    22. class UserView(APIView):
    23. authentication_classes = [MyAuthentication,]
    24. def get(self,request):
    25. return Response("UserView")
    26. class OrderView(APIView):
    27. authentication_classes = [MyAuthentication,]
    28. def get(self,request):
    29. return Response("OrderView")

    二、简单的实例

    上面快速应用,需要在每个视图中都加  authentication_classes 的设置,如果有100个都需要加,按照上面的方法就太繁琐了,所以DRF支持全局配置 authentication_classes ;

    还有一个需要注意的地方:全局设置 authentication_classes 的时候,自定义认证类不能在views.py中,要单独放到一个文件中,不然会引起反复调用,报错的问题。

    1、urls.py

    1. urlpatterns = [
    2. path('login/', views.LoginView.as_view()),
    3. path('user/', views.UserView.as_view()),
    4. path('order/', views.OrderView.as_view()),
    5. ]

    2、views.py

    1. class LoginView(APIView):
    2. # 排除页面设置为空就可以了;
    3. # 如果全局和局部都设置了,以局部为准;
    4. authentication_classes = []
    5. def get(self,request):
    6. return Response("LoginView")
    7. class UserView(APIView):
    8. def get(self,request):
    9. return Response("UserView")
    10. class OrderView(APIView):
    11. def get(self,request):
    12. return Response("OrderView")

    4、auth.py,在项目下新建一个文件夹,名字为ext,在该文件夹下建立auth.py文件,作为自定义认证类的存放地址

    1. from rest_framework.authentication import BaseAuthentication
    2. from rest_framework.exceptions import AuthenticationFailed # 认证失败抛出异常使用
    3. class MyAuthentication(BaseAuthentication):
    4. def authenticate(self, request):
    5. '''
    6. 重写这个方法,去做认证,
    7. 1、读取用户请求传递的token;
    8. 2、校验合法性;
    9. 3、返回值:
    10. - 返回一个元组(),认证成功:必须有2个元素,request.user request.auth
    11. - 认证失败,抛出异常,返回错误信息;
    12. - 返回None,在有多个认证类的时候,会依次认证; 都没有认证成功的话,默认为匿名用户;
    13. '''
    14. token = request.query_params.get("token")
    15. if token:
    16. return ("wupeiqi","123456")
    17. else:
    18. raise AuthenticationFailed("认证失败")
    19. # 解决抛出异常,状态码一致的问题;
    20. def authenticate_header(self, request):
    21. return "API"

    3、settings.py

    1. REST_FRAMEWORK = {
    2. # 自定义认证组件的全局配置
    3. "DEFAULT_AUTHENTICATION_CLASSES":['ext.auth.MyAuthentication',]
    4. }

    三、多个认证类的执行流程

    如果有多个认证类,执行流程是依次执行,直到最后。如果通过,后面不再执行。如果执行到最后都没有通过会返回None,匿名访问。 

    四、实例应用

    1、urls.py

    1. urlpatterns = [
    2. path('login/', views.LoginView.as_view()),
    3. path('user/', views.UserView.as_view()),
    4. path('order/', views.OrderView.as_view()),
    5. ]

    2、auth.py

    1. from rest_framework.authentication import BaseAuthentication
    2. from rest_framework.exceptions import AuthenticationFailed # 认证失败抛出异常使用
    3. from api import models
    4. # 在url中寻找token
    5. class QueryParamsAuthentication(BaseAuthentication):
    6. def authenticate(self, request):
    7. '''
    8. 重写这个方法,去做认证,
    9. 1、读取用户请求传递的token;
    10. 2、校验合法性;
    11. 3、返回值:
    12. - 返回一个元组(),认证成功:必须有2个元素,request.user request.auth
    13. - 认证失败,抛出异常,返回错误信息;
    14. - 返回None,在有多个认证类的时候,会依次认证; 都没有认证成功的话,默认为匿名用户;
    15. '''
    16. token = request.query_params.get("token")
    17. # 如果没有token 返回None
    18. if not token:
    19. return
    20. user_object = models.UserInfo.objects.filter(token=token).first()
    21. if user_object:
    22. return user_object,token # 这样 request.user= 用户对象,request.auth= token ;
    23. # 没有认证成功,返回none,继续去别的认证类中认证
    24. return
    25. # 解决抛出异常,状态码一致的问题;
    26. def authenticate_header(self, request):
    27. return "API"
    28. # 在请求头中寻找token
    29. class HeaderParamsAuthentication(BaseAuthentication):
    30. def authenticate(self, request):
    31. token = request.META.get("HTTP_AUTHORIZATION")
    32. # 如果没有token 返回None
    33. if not token:
    34. return
    35. user_object = models.UserInfo.objects.filter(token=token).first()
    36. if user_object:
    37. return user_object,token # 这样 request.user= 用户对象,request.auth= token ;
    38. # 没有认证成功,返回none,继续去别的认证类中认证
    39. return
    40. # 解决抛出异常,状态码一致的问题;
    41. def authenticate_header(self, request):
    42. return "API"
    43. # 都没找到token,抛出失败
    44. class NoAuthentication(BaseAuthentication):
    45. def authenticate(self, request):
    46. raise AuthenticationFailed({"code":1001,"msg":"认证失败"})
    47. # 解决抛出异常,状态码一致的问题;
    48. def authenticate_header(self, request):
    49. return "API"

    3、settings.py

    1. REST_FRAMEWORK = {
    2. "UNAUTHENTICATED_USER": None,
    3. "UNAUTHENTICATED_TOKEN": None,
    4. # 自定义认证组件的全局配置
    5. "DEFAULT_AUTHENTICATION_CLASSES":[
    6. 'ext.auth.QueryParamsAuthentication',
    7. 'ext.auth.HeaderParamsAuthentication',
    8. 'ext.auth.NoAuthentication',
    9. ]
    10. }

    4、models.py

    1. class UserInfo(models.Model):
    2. '''用户表'''
    3. username = models.CharField(verbose_name="用户名",max_length=32)
    4. password = models.CharField(verbose_name="密码",max_length=64)
    5. # 临时测试方法,token可以存放到很多地方,例如radis jwt等
    6. token = models.CharField(verbose_name="TOKEN",max_length=64,null=True,blank=True)

    5、views.py

    1. from rest_framework.response import Response
    2. from rest_framework.views import APIView
    3. from api import models
    4. import uuid # 用于生成token
    5. class LoginView(APIView):
    6. # login页面不需要认证就可以登录,所以单独设置为空;
    7. authentication_classes = []
    8. def post(self,request):
    9. # 1、接收用户提交的用户名和密码;
    10. user = request.data.get("username")
    11. pwd = request.data.get("password")
    12. # 2、数据库校验;
    13. user_object = models.UserInfo.objects.filter(username=user,password=pwd).first()
    14. if not user_object:
    15. return Response({"status":False,"msg":"用户名或者密码错误"})
    16. # 用户名密码正确为用户生产token
    17. token = str(uuid.uuid4())
    18. user_object.token = token
    19. user_object.save()
    20. return Response({"status":True,"msg":"登录成功!","token":token})
    21. class UserView(APIView):
    22. def get(self,request):
    23. print(request.user,request.auth)
    24. return Response("UserView")
    25. class OrderView(APIView):
    26. def get(self,request):
    27. return Response("OrderView")

     

     

  • 相关阅读:
    探索UI设计|栅格系统的深入分析和应用
    C# iText 7 切分PDF,处理PDF页面大小
    WebGPU入门
    爱上开源之golang入门至实战-第二章语言基础
    【CSS】font-weight设置为500显示不出加粗效果
    分布式存储系统之Ceph集群启用Dashboard及使用Prometheus监控Ceph
    基于STM32的多组外部中断(EXTI)的优化策略与应用
    React Native优质开源项目推荐与解析
    【无标题】
    基于nodejs的在线跑腿系统-计算机毕业设计
  • 原文地址:https://blog.csdn.net/weixin_47401101/article/details/134495444