DRF 认证

DRF 认证

解决你是谁的问题。

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

DRF提供的认证方案

  1. class BasicAuthentication(BaseAuthentication):
    
  2. class SessionAuthentication(BaseAuthentication):
    
  3. class TokenAuthentication(BaseAuthentication):
    
  4. class RemoteUserAuthentication(BaseAuthentication):
    

自定义Token认证

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

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    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)
  

定义注册登录视图

class RegisterView(APIView):

    def post(self, request):
        res = {"code": 0}
        username = request.data.get('username')
        password = request.data.get('password')
        if username and password:
            models.UserInfo.objects.create(username=username, password=password)
        else:
            res['code'] = 1
            res['error'] = '用户名或密码为空'
        return Response(res)


class LoginView(APIView):
    """
    校验用户名密码是否正确从而生成token的视图
    """

    def post(self, request):
        res = {"code": 0}
        username = request.data.get('username')
        password = request.data.get('password')
        user = models.UserInfo.objects.filter(username=username, password=password).first()
        if user:
            # 生成token
            token = uuid.uuid1()
            models.Token.objects.update_or_create(defaults={'token_code': token}, user=user)
            res['token'] = token
        else:
            res["code"] = 1
            res['error'] = '用户名或密码错误'

        return Response(res)

路由

urlpatterns = [

    url(r'^register/$', views.RegisterView.as_view()),
    url(r'^login/$', views.LoginView.as_view()),
]

定义一个认证类

class 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, request_token   # request.user,request.auth
       else:
           return None, None

视图级别认证

局部配置的优先级高于全局的配置

class AuthorListView(ListCreateAPIView):
    queryset = models.Author.objects.all()
    serializer_class = AuthorModelSerializer
    authentication_classes = [MyAuth, ]

全局级别认证

# 在settings.py中配置
REST_FRAMEWORK = {
    
    "DEFAULT_AUTHENTICATION_CLASSES": ["auth_app.auth.MyAuth", ]

}

源码分析

  1. 请求 ——》urls.py ——》as_view ——》APIView的dispatch方法——》

1561891528317

  1. 在 1 initialize_request 中 已经获取到了认证类

1561891662248

1561891678624

  1. 在 2 initial 中 进行认证

1561891770058

1561891059995

1561891888983

1561892338485

posted @ 2019-08-16 16:26  写bug的日子  阅读(107)  评论(0编辑  收藏  举报