rest_framework认证组件

问题:有些API,需要用户登录才能访问,有些无需登录就能访问。

解决:

  • a. 创建两个模型类:UserInfo---OneToOne---UsetToken

  • b. 登录成功后保存在数据库的UserToken表中

            # urls.py
    
            from django.urls import path
    from api import views urlpatterns = [
    path('api/v1/auth/',views.AuthView.as_view()),
    ] # views.py import hashlib, time
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from api import models def md5(username):
    """
    生成token
    :param username:
    :return:
    """
    m = hashlib.md5(username.encode('utf-8'))
    m.update(str(time.time()).encode('utf-8'))
    return m.hexdigest() class AuthView(APIView):
    """
    用户登录
    """ def post(self, request, *args, **kwargs):
    ret = {'code': 1000, 'msg': None}
    username = request._request.POST.get('username')
    password = request._request.POST.get('password') user = models.UserInfo.objects.filter(username=username, password=password).first()
    if not user:
    ret['msg'] = '用户名或密码错误'
    return Response(ret)
    token = md5(username)
    # 存在就更新,不存在就创建
    models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
    ret['code'] = 2000
    ret['msg'] = '登录成功'
    ret['token'] = token
    return Response(ret)
  • c. 创建自定义Auth认证类和订单,访问订单,判断是否携带token访问,不然不让访问


# urls.py urlpatterns = [
path('api/v1/auth/',views.AuthView.as_view()),
path('api/v1/order/',views.OrderView.as_view()),
] # views.py ORDERS = [
{
'id': '1',
'name': '华为MATE 20 Pro',
'price': 6999,
},
{
'id': '2',
'name': '一加6t',
'price': 3999,
},
{
'id': '3',
'name': '狗比亚',
'price': 2699,
},
] class Authentication(object):
"""
自定义认证类
""" def authenticate(self, request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
raise AuthenticationFailed('用户认证失败')
# 返回一个元祖 一个是用户对象。一个是token对象
return token_obj.user, token_obj def authenticate_header(self, request):
pass class OrderView(APIView):
"""
订单相关业务
"""
authentication_classes = [Authentication] def get(self, request, *args, **kwargs):
ret = {'code': 2000, 'msg': '获取成功', 'data': ORDERS}
return Response(ret)
  • d. 测试接口:只测试了正确的用户名和密码,错误的自己测

            import requests
    
            auth_url = 'http://127.0.0.1:8000/api/v1/auth/'
    res = requests.post(auth_url, data={'username': 'alex', 'password': 'root1234'}).json() print(res) # {'code': 2000, 'msg': '登录成功', 'token': '02fdedaa2c6c5773e00706b5890e289a'}
    token = res.get('token') order_url = 'http://127.0.0.1:8000/api/v1/order/'
    res = requests.get(order_url,params={'token':token}).json()
    print(res) # {'code': 2000, 'msg': '获取成功', 'data': [{'id': '1', 'name': '华为MATE 20 Pro', 'price': 6999}, {'id': '2', 'name': '一加6t', 'price': 3999}, {'id': '3', 'name': '狗比亚', 'price': 2699}]}
  • e. 再写一个API用户获取用户信息(通过认证通过后注册的request.user对象和request.token对象)


    urlpatterns = [
    path('api/v1/auth/',views.AuthView.as_view()),
    path('api/v1/order/',views.OrderView.as_view()),
    path('api/v1/user_info/',views.UserInfoView.as_view()),
    ] class UserInfoView(APIView):
    """
    获取用户信息相关
    """
    authentication_classes = [Authentication] def get(self, request, *args, **kwargs):
    data = {
    'username': request.user.username,
    'token': request.auth.token
    }
    ret = {'code': 2000, 'msg': '获取成功', 'data': data}
    return Response(ret)
  • f. 测试认证成功之后返回元祖的两个对象


    import requests auth_url = 'http://127.0.0.1:8000/api/v1/auth/'
    res = requests.post(auth_url, data={'username': 'alex', 'password': 'root1234'}).json() print(res) # {'code': 2000, 'msg': '登录成功', 'token': '05810e2756bc6cc27c1ce3af827aa45f'}
    token = res.get('token') order_url = 'http://127.0.0.1:8000/api/v1/user_info/'
    res = requests.get(order_url,params={'token':token}).json()
    print(res) # {'code': 2000, 'msg': '获取成功', 'data': {'username': 'alex', 'token': '05810e2756bc6cc27c1ce3af827aa45f'}}

全局使用(再次看源码)

      def get_authenticators(self):
return [auth() for auth in self.authentication_classes] authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES def reload_api_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'REST_FRAMEWORK':
api_settings.reload()
# 所以通过配置api.settings可达到全局使用的效果
  • 全局使用
   # 在api应用下面创建utils\auth.py 把之前写的自定义类剪切过来
# utils\auth.py
from api import models
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication class Authentication(BaseAuthentication):
"""
自定义认证类
""" def authenticate(self, request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
raise AuthenticationFailed('用户认证失败')
# 返回一个元祖 一个是用户对象。一个是token对象
return token_obj.user, token_obj def authenticate_header(self, request):
pass
# settings.py
##############rest_framework配置################
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':['api.utils.auth.Authentication']
}
# views.py
import hashlib, time
from rest_framework.views import APIView
from rest_framework.response import Response
from api import models ORDERS = [
{
'id': '1',
'name': '华为MATE 20 Pro',
'price': 6999,
},
{
'id': '2',
'name': '一加6t',
'price': 3999,
},
{
'id': '3',
'name': '狗比亚',
'price': 2699,
},
] def md5(username):
"""
生成token
:param username:
:return:
"""
m = hashlib.md5(username.encode('utf-8'))
m.update(str(time.time()).encode('utf-8'))
return m.hexdigest() class AuthView(APIView):
"""
用户登录
"""
# 不需要认证为空列表即可
authentication_classes = [] def post(self, request, *args, **kwargs):
ret = {'code': 1000, 'msg': None}
username = request._request.POST.get('username')
password = request._request.POST.get('password') user = models.UserInfo.objects.filter(username=username, password=password).first()
if not user:
ret['msg'] = '用户名或密码错误'
return Response(ret)
token = md5(username)
# 存在就更新,不存在就创建
models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
ret['code'] = 2000
ret['msg'] = '登录成功'
ret['token'] = token
return Response(ret) class OrderView(APIView):
"""
订单相关业务
""" def get(self, request, *args, **kwargs):
ret = {'code': 2000, 'msg': '获取成功', 'data': ORDERS}
return Response(ret) class UserInfoView(APIView):
"""
获取用户信息相关
""" def get(self, request, *args, **kwargs):
data = {
'username': request.user.username,
'token': request.auth.token
}
ret = {'code': 2000, 'msg': '获取成功', 'data': data}
return Response(ret)

梳理:

  • 全局使用:创建自定义认证类,继承BaseAuthentication,实现:authenticate()

  • 局部使用(使用自带的认证类):authentication_classes = [BasicAuthentication,]

  • 该方法有三种返回值

    1. None 当前认证类不做认证,交给下一个认证来来执行
    2. 抛出异常 raise AuthenticationFailed('用户认证失败')
    3. 元祖(元素1,元素2):元素1赋值给request.user;元素2赋值给request.token
  • 注意:当所有认证类都返回None时,此时是匿名用户,默认是AnonymousUser,可以通过配置文件来更改显示

    REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ],
#"UNAUTHENTICATED_USER":lambda :"匿名用户",
"UNAUTHENTICATED_USER":None, # 匿名,request.user = None
"UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
}

源码流程

  1. dispath()-->initialize_request()

    - 封装request对象,获取认证类(全局&局部),通过列表生成式创建认证类对象

  2. initial-->perform_authentication()-->request.user

    - for循环每个认证类 return

  3. 认证成功基于反射根据method不同做不同处理

002---rest_framework认证组件的更多相关文章

  1. Django的rest_framework认证组件之全局设置源码解析

    前言: 在我的上一篇博客我介绍了一下单独为某条url设置认证,但是如果我们想对所有的url设置认证,该怎么做呢?我们这篇博客就是给大家介绍一下在Rest_framework中如何实现全局的设置认证组件 ...

  2. Django的rest_framework认证组件之局部设置源码解析

    前言: Django的rest_framework组件的功能很强大,今天来我来给大家剖析一下认证组件 下面进入正文分析,我们从视图开始,一步一步来剖析认证组件 1.进入urls文件 url(r'^lo ...

  3. rest_framework -- 认证组件

    #####认证组件##### 一.认证是什么就不说了,某些网页必须是用户登陆之后,才能访问的,所以这时候就需要用上认证组件. 你不用rest_framework的认证组件也行,这种认证的话,完全可以自 ...

  4. Django之REST_FRAMEWORK 认证组件

    Django之DRF之认证组件 # from rest_framework.views import APIView # APIView 中的 dispatch 中 执行的 self.initial( ...

  5. rest_framework 认证组件 权限组件

    认证组件 权限组件 一.准备内容 # models class User(models.Model): name = models.CharField(max_length=32) pwd = mod ...

  6. DRF认证组件

    1.DRF认证组件之视图注册用法(自定义简单使用) settings.py配置 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.a ...

  7. Django-restframework 源码之认证组件源码分析

    Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...

  8. drf视图组件、认证组件

    视图组件 1.基本视图 url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>\d+)/$', vi ...

  9. DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

随机推荐

  1. Mybatis学习---Mybatis分页插件 - PageHelper

    1. Mybatis分页插件 - PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,S ...

  2. windows系统镜像 微软官方资源便捷下载教程

    今天跟小师弟学到了一个下载软件的好办法,省得到各种网站下载带有病毒,插件的资源. 这个神奇的网站叫做   MSDN, 我告诉你,这是一个私人维护的网站,里面有各种官方软件的下载地址.可以直接用下载工具 ...

  3. CentOS7.4 Keepalived+LVS 负载均衡 后台节点健康检查

    主机信息 VIP 10.10.10.55 LVS01 10.10.10.59 Web01 10.10.10.60 Web02 10.10.10.61 一.apache简单配置 1.(10.10.10. ...

  4. Oracle与EntityFramework(EF)的一些事情

    概要 Oracle 和EF 一起用的时候总会有各种问题,这里总结一下解决办法. 模式 Schema 用过Oracle的人应该知道,其实Oracle的用户名一般就是它的模式名称,如果你在用databas ...

  5. August 07th 2017 Week 32nd Monday

    Life is just a series of trying to make up your mind. 生活只是由一系列下决心的努力所构成. Some people say it is not y ...

  6. Genymotion安卓模拟器和VirtualBox虚拟机安装、配置、测试(win7_64bit)

    1.概述 VirtualBox是一个优秀的虚拟机软件,它可以在电脑上提供另一个操作系统的运行环境,使多个系统同时运行.VirtualBox支持的操作系统包括Windows.Mac OS X.Linux ...

  7. maven相关基础

    0. 本文主要参考一下良心maven原创文摘: 0.0 maven官网传送门 http://maven.apache.org/ 0.1 maven日常 http://www.cnblogs.com/x ...

  8. idea更新maven依赖包

    IntelljIdea 自动载入Maven依赖的功能很好用,但有时候会碰到问题,导致pom文件修改却没有触发自动重新载入的动作,此时需要手动强制更新依赖. 如下: (1)右键单击项目: (2)在弹出菜 ...

  9. hdu 1874 Dijkstra算法

    先贴个网上找的比较通俗易懂的教程: 2.1Dijkstra算法(非负权,使用于有向图和无向图) Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心 ...

  10. ZooKeeper学习之路 (五)ZooKeeper API的简单使用 增删改查

    zookeeper文件系统的增删改查 public class ZKDemo1 { private static final String CONNECT_STRING = "hadoop1 ...