2012-07-06 36 views
0

我已經實現了一個認證模式,模仿亞馬遜在我的Django網絡服務上用S3做的事情。每個請求都使用祕密進行簽名。要簽名的字符串除其他外還包括正在訪問的資源的URL。如何檢測客戶端用於訪問Django Web服務的實際URL?

例如,如果客戶端發出http://myservices.org/users的GET請求,則客戶端必須構造string_to_sign,其中包含http://myservices.org/users。當服務器處理請求時,它也會構造一個string_to_sign,並且可以根據它從WSGI包裝器請求對象獲知的信息包含相同的URL。

我的問題是,當客戶端決定包含端口號(例如http://myservices.org:80/users)時,服務器代碼將構造一個不正確的string_to_sign,因爲我不知道如何獲取客戶端使用的實際URL。 WSGI封裝器不讓我知道URL包含端口號。

有沒有辦法讓Django應用程序學習HTTP請求中的實際URL?我是否需要設置某種位於WSGI封裝器之前的請求處理程序,以便訪問原始HTTP請求並將URL自動抽出?

回答

1

你在問不可能。您所擁有的只是請求的第一行,不包括網絡位置(主機名和端口號)。您通常會得到一個主機頭(HTTP 1.0或更高版本),其中可能包含或不包含端口號。

你可能想看看django-fost-authn,它實現了一個非常類似於亞馬遜的方案。

即使你不使用,喜歡你自己的,你應該能夠看到如何請求正常化是那裏進行預簽名計算。最相關的觀察是它只使用HTTP請求本身內的因素。它允許添加自定義標題以包含在簽名的標題集中,並且您可以堅持要爲Host標題簽名。特別是在如何把文檔中FOST-authn/signature.py

1

產生雖然它可能並不總是與不同的瀏覽器和HTTP版本一起

瞧,你可以使用request.META['HTTP_HOST']。現在我的本地開發服務器會返回「localhost:8000」,然後我可以通過中間的冒號拆分,以便分開獲取這兩個部分。

此外,您可能會在HttpRequest類的get_host()方法中找到一些用法。從the Django documentation

返回使用從HTTP_X_FORWARDED_HOST信息的請求的源主機(如果USE_X_FORWARDED_HOST啓用)和HTTP_HOST頭,按照這個順序。如果他們不提供一個值,該方法使用SERVER_NAME和SERVER_PORT的組合如在PEP 3333

實施例詳述:「127.0.0.1:8000」