纵有疾风起
人生不言弃

Django REST framework基础:认证、权限、限制

 

认证、权限和限制

身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制。然后 权限 和 限制 组件决定是否拒绝这个请求。

简单来说就是:

认证确定了你是谁

权限确定你能不能访问某个接口

限制确定你访问某个接口的频率

认证

REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案。

Django REST framework基础:认证、权限、限制插图

 

接下类我们就自己动手实现一个基于Token的认证方案:

自定义Token认证

定义一个用户表和一个保存用户Token的表:

class UserInfo(models.Model):    username = models.CharField(max_length=16)    password = models.CharField(max_length=32)    type = models.SmallIntegerField(        choices=((1, '普通用户'), (2, 'VIP用户')),        default=1    )class Token(models.Model):    user = models.OneToOneField(to='UserInfo')    token_code = models.CharField(max_length=128)

定义一个登录视图:

def get_random_token(username):    """    根据用户名和时间戳生成随机token    :param username:    :return:    """    import hashlib, time    timestamp = str(time.time())    m = hashlib.md5(bytes(username, encoding="utf8"))    m.update(bytes(timestamp, encoding="utf8"))    return m.hexdigest()class LoginView(APIView):    """    校验用户名密码是否正确从而生成token的视图    """    def post(self, request):        res = {"code": 0}        print(request.data)        username = request.data.get("username")        password = request.data.get("password")        user = models.UserInfo.objects.filter(username=username, password=password).first()        if user:            # 如果用户名密码正确            token = get_random_token(username)            models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)            res["token"] = token        else:            res["code"] = 1            res["error"] = "用户名或密码错误"        return Response(res)

定义一个认证类

from rest_framework.authentication import BaseAuthenticationfrom rest_framework.exceptions import AuthenticationFailedclass MyAuth(BaseAuthentication):    def authenticate(self, request):        if request.method in ["POST", "PUT", "DELETE"]:            request_token = request.data.get("token", None)            if not request_token:                raise AuthenticationFailed('缺少token')            token_obj = models.Token.objects.filter(token_code=request_token).first()            if not token_obj:                raise AuthenticationFailed('无效的token')            return token_obj.user.username, None        else:            return None, None

视图级别认证

class CommentViewSet(ModelViewSet):    queryset = models.Comment.objects.all()    serializer_class = app01_serializers.CommentSerializer    authentication_classes = [MyAuth, ]

全局级别认证

# 在settings.py中配置REST_FRAMEWORK = {    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]}

权限

只有VIP用户才能看的内容。

自定义一个权限类

# 自定义权限class MyPermission(BasePermission):    message = 'VIP用户才能访问'    def has_permission(self, request, view):        """        自定义权限只有VIP用户才能访问        """        # 因为在进行权限判断之前已经做了认证判断,所以这里可以直接拿到request.user        if request.user and request.user.type == 2:  # 如果是VIP用户            return True        else:            return False

视图级别配置

class CommentViewSet(ModelViewSet):    queryset = models.Comment.objects.all()    serializer_class = app01_serializers.CommentSerializer    authentication_classes = [MyAuth, ]    permission_classes = [MyPermission, ]

全局级别设置

# 在settings.py中设置rest framework相关配置项REST_FRAMEWORK = {    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],    "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]}

限制

DRF内置了基本的限制类,首先我们自己动手写一个限制类,熟悉下限制组件的执行过程。

自定义限制类

VISIT_RECORD = {}# 自定义限制class MyThrottle(object):    def __init__(self):        self.history = None    def allow_request(self, request, view):        """        自定义频率限制60秒内只能访问三次        """        # 获取用户IP        ip = request.META.get("REMOTE_ADDR")        timestamp = time.time()        if ip not in VISIT_RECORD:            VISIT_RECORD[ip] = [timestamp, ]            return True        history = VISIT_RECORD[ip]        self.history = history        history.insert(0, timestamp)        while history and history[-1] < timestamp - 60:            history.pop()        if len(history) > 3:            return False        else:            return True    def wait(self):        """        限制时间还剩多少        """        timestamp = time.time()        return 60 - (timestamp - self.history[-1])

 

视图使用

class CommentViewSet(ModelViewSet):    queryset = models.Comment.objects.all()    serializer_class = app01_serializers.CommentSerializer    throttle_classes = [MyThrottle, ]

全局使用

# 在settings.py中设置rest framework相关配置项REST_FRAMEWORK = {    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],    "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]    "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]}

使用内置限制类

from rest_framework.throttling import SimpleRateThrottleclass VisitThrottle(SimpleRateThrottle):    scope = "xxx"    def get_cache_key(self, request, view):        return self.get_ident(request)

全局配置

# 在settings.py中设置rest framework相关配置项REST_FRAMEWORK = {    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],    # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]    "DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ],    "DEFAULT_THROTTLE_RATES": {        "xxx": "5/m",    }}

 

文章转载于:https://www.cnblogs.com/liwenzhou/p/9410737.html

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » Django REST framework基础:认证、权限、限制
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录