zoukankan      html  css  js  c++  java
  • DRF--认证和权限

    前戏

    大家都知道http协议是无状态的,每次发送请求他们怎么知道我们是不是登录过呢?我们可以在用户登录之后给用户一个“暗号”,下次请求的时候带着这个“暗号”来。我们拿自己存的和携带过来的进行对比,如果一样,就可以认为是登录过的。

    认证

    先来创建一张用户表

    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        token = models.UUIDField(null=True, blank=True)  # 随机字符串

    在进行数据库的迁移,在数据库里添加几条数据。

    接下来就可以写我们的认证了,新建个py文件,写入如下内容,假设前端妹子给我们传来的token是在url里

    from .models import User
    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework.authentication import BaseAuthentication
    
    
    class MyAuth(BaseAuthentication):
        def authenticate(self, request):  # 必须是这个函数名
            # 拿到前端传来的token,判断token是否存在
            token = request.query_params.get('token', '')
            if not token:
                raise AuthenticationFailed("缺少token")
            user_obj = User.objects.filter(token=token).first()
            if not user_obj:
                raise AuthenticationFailed("token不合法")
            return (user_obj, token)
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from course.models import Account
    from django.utils.timezone import now  # 要用django提供的时间
    
    
    class MyAuth(BaseAuthentication):
        def authenticate(self, request):
            if request.method == 'OPTIONS':  #过滤掉options请求
                return None
            # 拿到前端传来的token,请求头的数据都在request.META里
            # 比如前端把token放在请求头里:authenticate:85ada55664sfqq6
            # django会在前面加上 HTTP_ 并转为大写,也就是 HTTP_AUTHENTICATE
            # print(request.META)
            token = request.META.get('HTTP_AUTHENTICATE', '')
    
            # 判断是否有这个token
            if not token:
                raise AuthenticationFailed({"code": 1020, "error": "没有token"})
            user_obj = Account.objects.filter(token=token).first()
            if not user_obj:
                raise AuthenticationFailed({"code": 1021, "error": "token不合法"})
    
            # 判断token是否过期
            old_time = user_obj.create_token_time  # 数据库里存的token的时间
            now_time = now()  # 用django提供获取时间的方法
            if (now_time - old_time).days > 7:
                raise AuthenticationFailed({"code": 1022, "error": "token已过期,请重新登录"})
            return (user_obj, token)
    token在请求头里

    写个视图测试

    class TestView(APIView):
        # 添加认证
        authentication_classes = [MyAuth,]  # 必须为可迭代对象
        def get(self, request):
            return Response('认证')

    这样只是个一个方法添加了认证,也可以添加全局的认证,在settings.py文件里

    REST_FRAMEWORK = {
        # 默认使用的版本控制类
        'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
        # 允许的版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],
        # 版本使用的参数名称
        'VERSION_PARAM': 'version',
        # 默认使用的版本
        'DEFAULT_VERSION': 'v1',
        # 配置全局认证
        'DEFAULT_AUTHENTICATION_CLASSES': ["BRQP.utils.MyAuth", ]
    }

    全局认证后在不需要认证的类中添加 authentication_classes = []

     权限

    我们都看过app上的电影,vip可以看一些视频,不是vip就看不了。因为vip的权限比非vip的权限大。那程序中的权限是什么样的呢?假设我们有一个系统,里面有添加学员,查看学员的功能。有些用户两个功能都有,而有些用户只有添加学员的功能。这里就要用到权限控制了。

    在DRF的源码里,权限是在认证之后的。我们在执行权限的时候,认证已经执行结束了。

    我们的权限类一定要有个has_permission方法,否则会抛出异常。

    我们来写一个权限的demo。在上面的model类里给表在加一个type类,表示我们的权限。

    from django.db import models
    
    
    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        token = models.UUIDField(null=True, blank=True)  # 随机字符串
        type = models.IntegerField(choices=((1, '普通用户'), (2, 'vip用户')), default=1)  # 权限字段

    在设置一个路由

    from django.conf.urls import url ,include
    from .views import LoginView, TestView, TestPermission
    
    urlpatterns = [
        url(r'^login/', LoginView.as_view()),
        url(r'^test/', TestView.as_view()),  
        url(r'^permission/', TestPermission.as_view()),  # 权限路由
    
    
    ]

    然后我们去写我们的权限类,新建一个permission.py文件

    class MyPermission(object):
        message = '权限不足'  # 提示信息
    
        def has_permission(self, request, view):  # 必须这个名
            # 权限逻辑,认证已经执行完了
            user_obj = request.user  # 因为认证已经执行完了,所以有request.user
            print(user_obj)
            if user_obj.type == 1:  # 返回的是个布尔值
                return False
            else:
                return True

    在去写我们的测试视图

    class TestPermission(APIView):
        authentication_classes = [MyAuth, ]  # 认证
        permission_classes = [MyPermission, ]  # 权限
    
        def get(self, request):
            return Response("恭喜你,你有访问权限")

    当有权限时(type=2)

     无权限时(type=1)

     DRF也给我们提供了一些权限类,都在permission类里

    from rest_framework import permissions
  • 相关阅读:
    【Vuejs】509- vue-loader工作原理
    【JS】508- MVVM原理介绍
    【Webpack】507- 基于Tree-shaking的多平台Web代码打包实践
    【TS】506- TypeScript 交叉类型
    【WebSocket】505- WebSocket 入门到精通
    【语雀知识库分享】HTTP面试宝典
    【JS】504- HTML5 之跨域通讯(postMessage)
    jQuery 选择器
    JQuery简介
    什么是JDBC的最佳实践?
  • 原文地址:https://www.cnblogs.com/zouzou-busy/p/11581084.html
Copyright © 2011-2022 走看看