2012-08-02 8 views
23

私はカスタム認証でis_authenticatedをオーバーライドしようとしています。tastypieを使ってdjangoにログインする方法

class MyAuthentication(BasicAuthentication): 
    def __init__(self, *args, **kwargs): 
     super(MyAuthentication, self).__init__(*args, **kwargs) 

    def is_authenticated(self, request, **kwargs): 
     return True 

その後、私のModelResourceに私は

class LoginUserResource(ModelResource): 

    class Meta: 
     resource_name = 'login' 
     queryset = User.objects.all() 
     excludes = ['id', 'email', 'password', 'is_staff', 'is_superuser'] 
     list_allowed_methods = ['post'] 

     authentication = MyAuthentication() 
     authorization = DjangoAuthorization() 

を持って、私は"error_message": "column username is not unique"バック500エラーを取得しておいてください。私はこのような単純なものを(で開始する)を持っています。私はdbに1つのユーザー名しか持っていません。それは認証しようとしているユーザーです。

なぜこのエラーが返されますか?どうすればapiクライアントにログインさせることができますか?

ありがとうございます。

+0

また、私はsqlite、python 2.7、django 1.4を使用しています。 – imns

答えて

69

あなたの方法では、認証しているユーザー名で新しいユーザーを作成しようとします。これは、あなたが気づいたように、そのようなユーザーがすでに存在していることをDBレイヤーにバブルアップします。

UserResourceを作成し、そこにユーザーが投稿し、ユーザー名/パスワードで渡すデータでログインできる方法を追加することです。

from django.contrib.auth.models import User 
from django.contrib.auth import authenticate, login, logout 
from tastypie.http import HttpUnauthorized, HttpForbidden 
from django.conf.urls import url 
from tastypie.utils import trailing_slash 

class UserResource(ModelResource): 
    class Meta: 
     queryset = User.objects.all() 
     fields = ['first_name', 'last_name', 'email'] 
     allowed_methods = ['get', 'post'] 
     resource_name = 'user' 

    def override_urls(self): 
     return [ 
      url(r"^(?P<resource_name>%s)/login%s$" % 
       (self._meta.resource_name, trailing_slash()), 
       self.wrap_view('login'), name="api_login"), 
      url(r'^(?P<resource_name>%s)/logout%s$' % 
       (self._meta.resource_name, trailing_slash()), 
       self.wrap_view('logout'), name='api_logout'), 
     ] 

    def login(self, request, **kwargs): 
     self.method_check(request, allowed=['post']) 

     data = self.deserialize(request, request.raw_post_data, 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) 
       return self.create_response(request, { 
        'success': True 
       }) 
      else: 
       return self.create_response(request, { 
        'success': False, 
        'reason': 'disabled', 
        }, HttpForbidden) 
     else: 
      return self.create_response(request, { 
       'success': False, 
       'reason': 'incorrect', 
       }, HttpUnauthorized) 

    def logout(self, request, **kwargs): 
     self.method_check(request, allowed=['get']) 
     if request.user and request.user.is_authenticated(): 
      logout(request) 
      return self.create_response(request, { 'success': True }) 
     else: 
      return self.create_response(request, { 'success': False }, HttpUnauthorized) 

今、あなたは、データ { 'username' : 'me', 'password' : 'l33t' }http://hostname/api/user/loginにPOSTを送信行うことができます。

+0

ありがとう、これは素晴らしいですね。私が混乱している唯一のことは、この行 'PublicModelResource.Meta'です。 PublicModelResourceとは何ですか? – imns

+0

これを無視して、別のものから誤って入力しただけです。正規のメタクラスを反映するように答えを修正しました。 – astevanovic

+0

このアプローチではセキュリティ上の問題が発生することはありません.GET/userで/ユーザーのハッシュパスワードを確認できるようになり、正しいアルゴリズムでプレーンテキストのパスワードを取得できるようになります。 – Milind

1

この更新プログラムは、GETメソッドのセキュリティ上の問題を解決します。 Djangoでの作業1.5.4。

class UserResource(ModelResource): 

    class Meta: 
     queryset = User.objects.all() 
     resource_name = 'user' 
     allowed_methods = ['post'] 


    def prepend_urls(self): 
     return [ 
      url(r"^user/login/$", self.wrap_view('login'), name="api_login"), 
      url(r"^user/logout/$", self.wrap_view('logout'), name='api_logout'), 
     ] 

    def login(self, request, **kwargs): 
     self.method_check(request, allowed=['post']) 

     data = self.deserialize(request, request.raw_post_data, 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) 
       return self.create_response(request, { 
        'success': True 
       }) 
      else: 
       return self.create_response(request, { 
        'success': False, 
        'reason': 'disabled', 
       }, HttpForbidden) 
     else: 
      return self.create_response(request, { 
       'success': False, 
       'reason': 'incorrect', 
       }, HttpUnauthorized) 

    def logout(self, request, **kwargs): 
     self.method_check(request, allowed=['post']) 
     if request.user and request.user.is_authenticated(): 
      logout(request) 
      return self.create_response(request, { 'success': True }) 
     else: 
      return self.create_response(request, { 'success': False }, HttpUnauthorized) 
+0

raphodn(コメントが不十分な担当者)から:* ktswのすばらしい答え、request.raw_post_dataは廃止予定です。request.body * –

+1

@ktswこれでGETのセキュリティ上の問題は解決しましたか?選択された回答のコメントから、その答えはセキュリティの問題ではないようです。また、ログアウトメソッドでは取得のみが許可されていますが、loginメソッドは投稿を許可します "" " –

関連する問題