2014-08-29 75 views
1

我有一個Django Web應用程序,需要在整個站點進行身份驗證。我已經用自定義中間件完成了這個工作,它基本上測試request.user.is_anonymous,如果它們是,將它們重定向到登錄頁面。它看起來像這樣:Django,TastyPie,身份驗證和自定義中間件頭痛

from django.contrib.auth.views import login 
from django.contrib.auth import authenticate 
from django.http import HttpResponseRedirect, HttpResponse 
from django.utils import simplejson 
from django.core import serializers 

class SiteLogin: 
    "This middleware requires a login for every view" 
    def process_request(self, request): 
     if request.path != '/accounts/login/' and request.user.is_anonymous(): 
      if request.POST: 
       return login(request) 
      else: 
       return HttpResponseRedirect('/accounts/login/?next=%s' % request.path) 

現在我正在做一個iOS應用其中,現在,將只是不下車Django的服務器請求。我正在嘗試使用TastyPie來做到這一點,但我無法使認證工作。我正在使用ApiKeyAuthentication,我相信它已經正確安裝。但是,它只是將我重定向到登錄頁面。我想知道是否需要編輯這個中間件來處理TastyPie請求,但我認爲TastyPie可以爲我授權...

我覺得我的情況與this question非常相似,但是我不知道我的自定義中間件正在阻礙。

這裏是我的api.py

from django.contrib.auth.models import User 
from django.db import models 
from tastypie.resources import ModelResource 
from cpm.systems.models import System 
from cpm.products.models import Product 
from tastypie.models import create_api_key 
from tastypie.authentication import ApiKeyAuthentication 
from tastypie.authorization import DjangoAuthorization, Authorization 

models.signals.post_save.connect(create_api_key, sender=User) 



class SystemResource(ModelResource): 
    class Meta: 
    queryset = System.objects.all() 
    resource_name = 'system' 
    authentication = ApiKeyAuthentication() 
    authorization = DjangoAuthorization() 


class ProductResource(ModelResource): 
    class Meta:  
    queryset = Product.objects.all() 
    resource_name = 'product' 
    authentication = ApiKeyAuthentication() 
    authorization = DjangoAuthorization() 

的一部分和我urls.py

from cpm.ios.api import SystemResource, ProductResource 
from tastypie.api import Api 

v1_api = Api(api_name='v1') 
v1_api.register(SystemResource()) 
v1_api.register(ProductResource()) 

admin.autodiscover() 

urlpatterns = patterns('', 

    # iOS TastyPie related: 
    (r'^ios/', include(v1_api.urls)), 
    # .... more urls.... 

我嘗試導航的網址是:

http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345?format=json 

但我只是重定向到我的登錄頁面。我按照教程進行了開球,在我的管理面板上創建了一個api鍵,並將WSGIPassAuthorization On添加到了我的apache配置中。

任何想法?

編輯我只是刪除中間件乾脆現在我收到的401驗證錯誤...

EDIT 2 我要指出的是,如果我刪除​​然後我得到一個回覆:Sorry, not implemented yet. Please append "?format=json" to your URL.。所以它就像確實進行身份驗證,但然後失敗,因爲我沒有指定格式。

所以我的網址看起來像這樣:http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345但是隻要我加上?format=JSON那麼它就會出現401錯誤。

+1

Re:format = JSON。當你將一對追加到查詢字符串時,?僅在開始時使用。其餘的對由&分開。所以,你的查詢字符串/ url應該看起來像 - http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345&format=JSON – dekomote 2014-08-29 22:13:04

+0

@dekomote - 哇 - 這工作!好的,所以我更近了一步。只要我*不使用我的自定義中間件,我現在就可以正確地進行身份驗證。所以這是一個很好的進展。所以這個問題的後半部分仍然存在 - 我的中間件。py(顯示在問題中)現在正在妨礙中。我把它設置錯了嗎?不應該TastyPie能夠爲我導航/驗證,從而繞過我的中間件? – Garfonzo 2014-08-29 22:19:06

回答

2

TastyPie請求通過與任何典型的django請求相同的堆棧中間件。所以,這絕對是你的中間件。你必須重新思考它,或者放棄基礎並使用@login_required。

由於您的URL格式不正確,因此禁用中間件後,api鍵不起作用。你不能使用?在你使用一次後查詢字符串。試試這個網址:

http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345&format=JSON 
+0

是的 - 這是我的問題,URL不正確。所以,我有很多意見(這是一個很大的公司網站)。這是否意味着我需要用'@ login_required'來裝飾它們*全部*只是爲了讓tastypie能夠做到這一點? – Garfonzo 2014-08-29 22:20:11

+0

那麼,你可以有很多方法:如果你使用基於類的視圖,你可以添加一個mixin來處理它。您可以添加中間件,但檢查請求是否會提供視圖... – dekomote 2014-08-29 22:23:09

+0

好吧,很酷,想一想。至少我知道我的問題的根源是什麼,並且至少可以確定解決問題的好方法。謝謝你的幫助!過去48小時我一直在拉我的頭髮! – Garfonzo 2014-08-29 22:24:39