使用mongoengine进行tastypie中的ApiKey身份验证

时间:2013-09-30 20:12:00

标签: api restful-authentication mongoengine tastypie

有没有人从mongoengine.django.auth成功实施ApiKey for User用于tastypie ApiKeyAuthentication?

我知道之前有关此事的帖子,但他们只讨论ORM,而我正在尝试为mongoengine设置它。此外,似乎tastypie自己的ApiKey类严重依赖于关系结构(使用User的相关字段api_key

提前感谢!

1 个答案:

答案 0 :(得分:1)

跟随这个帖子https://github.com/mitar/django-tastypie-mongoengine/issues/25我用api_key字段创建了MongoUser类

# models.py (or documents.py)
from mongoengine.django.auth import User

class MongoUser(User):
    """
    Subclass of mongoengine.django.auth.User with email as username
    and API key for authentication.
    """
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['password']

    api_key = StringField(max_length=256, default='')
    api_key_created = DateTimeField(help_text=_(u'Created'))

    def save(self, *args, **kwargs):
        if not self.api_key:
            self.set_api_key()

        return super(MongoUser, self).save(*args, **kwargs)

    def set_api_key(self):
        self.api_key = self.generate_key()
        self.api_key_created = datetime.now()

    def generate_key(self):
        new_uuid = uuid.uuid4()
        return hmac.new(str(new_uuid), digestmod=sha1).hexdigest()

添加了一个信号(通常):

# resources.py
from mongoengine import signals
from myapp import models
signals.post_save.connect(create_api_key, sender=models.MongoUser)

然后使用以下内容对tastypie.ApiKeyAuthentication进行子类化:

# resources.py
class CustomApiKeyAuthentication(ApiKeyAuthentication):
    """
    Authenticates everyone if the request is GET otherwise performs
    ApiKeyAuthentication.
    """
    def is_mongouser_authenticated(self, request):
        """
        Custom solution for MongoUser ApiKey authentication.
        ApiKey here is not a class (as it is realized in ORM approach),
        but a field MongoUser class.
        """
        username, api_key = super(CustomApiKeyAuthentication,
                                  self).extract_credentials(request)
        try:
            models.MongoUser.objects.get(username=username, api_key=api_key)
        except models.MongoUser.DoesNotExist:
            return False

        return True

    def is_authenticated(self, request, **kwargs):
        """
        Custom solution for `is_authenticated` function: MongoUsers has got
        authenticated through custom api_key check.
        """
        if request.method == 'GET':
            return True
        try:
            is_authenticated = super(CustomApiKeyAuthentication,
                                     self).is_authenticated(request, **kwargs)
        except TypeError as e:
            if "MongoUser" in str(e):
                is_authenticated = self.is_mongouser_authenticated(request)
            else:
                is_authenticated = False
        return is_authenticated