• Django REST framework


    认证

    (我是谁?)

    身份认证是将传入请求与一组标识凭据相关联的机制,然后,权限和限制策略可以使用这些凭据来确定是否应该允许该请求.

    REST框架提供了许多开箱即用的身份验证方案,还允许您实现自定义方案。
    身份验证始终在视图的最开始,在发生权限和限制检查之前,以及允许任何其他代码继续之前运行。

    request.user 属性通常将设置为contrib.authUser类的实例。

    request.auth 属性用于任何其他身份验证信息,例如,它可用于表示请求已签名的身份验证令牌。

    DRF 5种验证方式

    # 基于用户名和密码的认证
    class BasicAuthentication(BaseAuthentication):
    	pass
    
    # 基于Session的认证
    class SessionAuthentication(BaseAuthentication):
    	pass
    
    # 基于Tokend的认证
    class TokenAuthentication(BaseAuthentication):
    	pass
    
    # 基于远端用户的认证(专用用户管理服务器)
    class TokenAuthentication(BaseAuthentication):
    	pass
    

    如何确定身份验证?

    身份验证方案始终定义为类列表。REST框架将尝试对列表中的每个类进行身份验证,并将设置request.user和request.auth使用成功进行身份验证的第一个类的返回值。

    如果没有类进行身份验证,request.user则将设置为实例django.contrib.auth.models.AnonymousUser,request.auth并将其设置为None。

    的价值request.user和request.auth对身份认证的请求可以通过修改UNAUTHENTICATED_USER和UNAUTHENTICATED_TOKEN设置。

    设置身份验证方案

    1. 可以使用该DEFAULT_AUTHENTICATION_CLASSES设置全局设置默认认证方案。例如

       REST_FRAMEWORK = {
       	'DEFAULT_AUTHENTICATION_CLASSES': (
           	'rest_framework.authentication.BasicAuthentication',
           	'rest_framework.authentication.SessionAuthentication',
      	 )
       }
      
    2. 您还可以使用APIView基于类的视图在每个视图或每个视图集的基础上设置身份验证方案。

       from rest_framework.authentication import SessionAuthentication, BasicAuthentication
       from rest_framework.permissions import IsAuthenticated
       from rest_framework.response import Response
       from rest_framework.views import APIView
       
       class ExampleView(APIView):
           authentication_classes = (SessionAuthentication, BasicAuthentication)
           permission_classes = (IsAuthenticated,)
       
           def get(self, request, format=None):
               content = {
                   'user': unicode(request.user),  # `django.contrib.auth.User` instance.
                   'auth': unicode(request.auth),  # None
               }
               return Response(content)
      
    3. 或者,如果您正在使用@api_view具有基于功能的视图的装饰器。

       @api_view(['GET'])
       @authentication_classes((SessionAuthentication, BasicAuthentication))
       @permission_classes((IsAuthenticated,))
       def example_view(request, format=None):
           content = {
               'user': unicode(request.user),  # `django.contrib.auth.User` instance.
               'auth': unicode(request.auth),  # None
           }
           return Response(content)
      

    案例: 基于自定义Token认证

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

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

    第二步: 定义一个登陆视图

    from rest_framework.views import APIView
    from app2 import models
    from rest_framework.response import Response
    import hashlib, time
    
    def get_random_token(username):
        """
        根据用户名和时间戳生成随机token
        """
        timestamp = str(time.time())
        m = hashlib.md5(bytes(username, encoding="utf-8"))
        m.update(bytes(timestamp, encoding="utf-8"))
        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 BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from app2 import models
    
    
    class MyAuth(BaseAuthentication):
        def authenticate(self, request):
            # if request.method in ["POST", "PUT", "DELETE"]:  
            
            # 如果在表单中需要判断请求方式    由于表单是post请求,所以获取token 的方式为 request.data.get("token")
            # request.query_params为url中的参数
            request_token = request.query_params.get("token", None)  
            if not request_token:
                raise AuthenticationFailed('q.缺少token')
    
            token_obj = models.Token.objects.filter(token_code=request_token).first()
            if not token_obj:
                raise AuthenticationFailed("无效的Token")
            # token_obj.user 通过token这张表的对象和user这个关联字段 找到 UserInfo表的对象及当前用户对象
            return token_obj.user, request_token
            
            # 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", ]
    }
  • 相关阅读:
    Failed to connect to remote VM
    在hibernate中实现oracle的主键自增策略
    Eclipse快捷键大全(转载)
    hibernate 中 get、load 的 区别
    Spring2.5的新特性:第一部分
    返回上一页代码实现
    Java与Json的使用方法介绍
    也悼念那个伟大的公司
    MFC/C++检查文件是否存在
    新一代开源VoIP协议栈--OPAL(OpenH323 v2)
  • 原文地址:https://www.cnblogs.com/konghui/p/10351910.html
Copyright © 2020-2023  润新知