tastypie - 从手机登录到Django,如何设置ApiKeyAuthentication

时间:2014-11-15 21:36:05

标签: django login django-models tastypie api-key

我已经在Django项目中设置了Tastypie,并且API正确地提供了资源。我现在正尝试允许移动用户(应用程序)通过所述API进行注册,登录和注销。

class BaseResource(ModelResource):

    class Meta:
        allowed_methods = [ 'get' ]
        authentication  = BasicAuthentication()
class UserResource(BaseResource):

    class Meta:
        queryset      = User.objects.all()
        resource_name = 'users'
        ...


class ProfileResource(BaseResource):

    class Meta:
        queryset      = Profile.objects.all()
        resource_name = 'profiles'
        ...

所以这是我的第一个目的。关于登录,我不认为BasicAuthentication被用于移动设备的请求。根据我的阅读,似乎有几种方法可以做我想要的事情:

第一个链接(请参阅the answer)让我烦恼的是移动应用程序必须发送包含原始密码的JSON:

{ 'username' : 'me', 'password' : 'l33t' }

是否有人/东西可以获取此JSON,从而可以访问密码?使用ApiKeyAuthentication不是更好吗?

我越来越明白我读到的内容越来越少。如果该帐户是从网络平台(django-userena)创建的,则我无法使用ApiKeyAuthentication,因为应创建密钥when a new User is saved

我可以找到几种方法来做我想做的事情,而且我找不到正确的一个......我确实已经意识到这个问题已被多次询问和回答,但我和#39;正在寻找关于以最佳方式实现这一点的方向。

1 个答案:

答案 0 :(得分:0)

我最终做了以下事情:

# ──────────────────────────────────────────────────────────────────────────────
class BaseResource(ModelResource):

    # ──────────────────────────────────────
    def prepend_urls(self):
        try:
            additional_urls = self._meta.additional_urls
        except AttributeError:
            additional_urls = []
        return [url(r'^'+u[0]+'$', self.wrap_view(u[1]), name=u[2]) for u in additional_urls]

    # ──────────────────────────────────────
    def update_in_place(self, request, original_bundle, new_data):
        try:
            allowed_fields = self._meta.allowed_fields
        except AttributeError:
            allowed_fields = None
        if allowed_fields and set(new_data.keys()) - set(allowed_fields):
            raise BadRequest('Only alterable field(s): {}'.format(', '.join(allowed_fields)))
        return super(ProfileResource, self).update_in_place(request, original_bundle, new_data)

    # ──────────────────────────────────────
    class Meta:
        abstract = True
        allowed_methods = ['get',]
        authentication  = ApiKeyAuthentication()
        authorization   = DjangoAuthorization()
        max_limit = 1000
# ──────────────────────────────────────────────────────────────────────────────
class UserResource(BaseResource):

    ...

    # ──────────────────────────────────────
    def signup(self, request, **kwargs):
        ...

    # ──────────────────────────────────────
    def signin(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        data = self.deserialize(
            request,
            request.body,
            format=request.META.get('CONTENT_TYPE', 'application/json')
        )
        username = data.get('username', '')
        password = data.get('password', '')
        user = authenticate(username=username, password=password)
        if user:
            if user.is_active:
                # login(request, user)
                try:
                    key = ApiKey.objects.get(user=user)
                    if not key.key:
                        key.save()
                except ApiKey.DoesNotExist:
                    key = ApiKey.objects.create(user=user)
                return self.create_response(request, {
                    'success': True,
                    'data': key.key,
                })
            else:
                return self.create_response(request, {
                    'success': False,
                    'message': 'User is not active',
                }, HttpForbidden)
        else:
            return self.create_response(request, {
                'success': False,
                'message': 'Wrong password',
                }, HttpUnauthorized)

    # ──────────────────────────────────────
    class Meta(BaseResource.Meta):
        allowed_methods = ['get', 'patch',]
        queryset        = User.objects.all()
        resource_name   = 'users'
        excludes        = [ 'first_name', 'last_name', 'password' ]
        filtering = {
            ...
        }
        additional_urls = [
            ('signup/', 'signup', 'api-signup'),
            ('signin/', 'signin', 'api-signin'),
        ]
        allowed_fields = ['email',]