DRF使用非模型字段来验证凭据

时间:2019-02-03 03:54:25

标签: python oauth-2.0 django-rest-framework

因此,我一直在尝试实现一种仅允许DRF REST API的注册功能仅由我的应用使用的方法。我知道任何人都可以访问该API,但是我想到要求在字段中输入client_id和client_secret,以便只有通过我的Oauth2协议注册的应用程序才能使用它。

我可以使用Oauth2成功登录我的应用程序并访问受限页面。我可以在此实现中注册,但会引发“用户对象没有属性client_id”的错误。

这是有道理的,因为client_id来自oauth2,但是我只希望此字段确保它仅由我的应用程序使用。

serializers.py

class UserSerializer(serializers.ModelSerializer):

    # Additional fields to verify if allowed to register with client info
    client_id = serializers.CharField(max_length=255)
    client_secret = serializers.CharField(max_length=255)

    class Meta:
        model = User # for the User model, use get_user_model for custom
        fields = ('id', 'username', 'password', 'email', 'first_name', 'last_name', 
            'client_id', 'client_secret',)
        extra_kwargs = {'password': {'write_only': True}}
        read_only_fields = ('id',)

    # override create method
    def create(self, validated_data):
        if validated_data['client_id'] != "OI430uPmYGKUJ6h2C7Ohjdn2C9i3WONVMi7WQvu0" and validated_data['client_secret'] != "X8KJNUjIeXf7I8jIbzjt4k92rs6OPxSUqKv9IeaP6YRpLsK8YZVDLK8RcFDqacH4hKSzkuuZET42VyMkIltQt8mUwi16DCGwFWX3fJf7ZxcDMKA6wOQKJnX1GKh9bQ7a":
            raise serializers.ValidationError("Not allowed to do this MATE!")

        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name']
            )

        user.set_password(validated_data['password'])
        user.save()

        return user

我实际上可以使用它来注册用户,但是抛出一个错误,指出该模型不包含client_id。我不确定该如何解决

我正在使用oauth2_provider

1 个答案:

答案 0 :(得分:0)

您对客户端ID和机密的想法是正确的,尤其是在使用OAuth2身份验证/授权协议时,但是您以错误的方式实现了该

首先,让我建议您将它们传递给标头,因为它们是身份验证凭据,就像Authorization标头一样。这是惯例。您可以为其创建自定义标头,也可以将它们添加到“授权”标头中。无论如何,不​​应在视图级别进行处理,而应在身份验证级别进行处理。

第二,如果要向模型序列化器中添加非模型字段,则应确保该字段不可写,因为序列化器在构建其字段时会引发错误。

查看Oauth2_provider docs,您可以看到已经实现了带有客户端ID和客户端密码的应用程序身份验证。

首先,您创建一个应用程序(例如,您的官方客户端应用程序)。将为该应用程序生成一个客户端ID和密码。然后,在注册新用户时,您将如以下示例所示传递此令牌:

curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/

这将为该应用程序(或客户端)返回唯一的用户身份验证凭据,这是进一步请求所必需的。

如果仅使用应用程序凭据即可对未注册用户进行应用程序身份验证,则应实现一个继承自oauth2_provider.contrib.rest_framework.OAuth2Authentication的自定义身份验证类,并在其中添加验证逻辑。不要忘记在REST_FRAMEWORK设置中将新类用作DEFAULT_AUTHENTICATION_CLASSES