簡體   English   中英

在Django中通過IP地址進行身份驗證

[英]Authenticate by IP address in Django

我有一個小的Django應用程序,我想限制某些用戶。 來自特定網絡的任何人都應該能夠在沒有任何進一步身份驗證的情況下看到該視圖,僅基於IP地址。 應該要求來自此IP范圍之外的任何其他人使用密碼並根據默認的Django用戶管理進行身份驗證。

我假設我必須為此編寫自定義身份驗證后端,但文檔讓我感到困惑,因為authenticate()函數似乎需要用戶名/密碼組合或令牌。 我不清楚如何使用IP地址進行身份驗證。

在Django中實現基於IP地址的身份驗證的正確方法是什么? 我寧願盡可能多地使用現有的庫函數來處理與安全相關的代碼,而不是自己編寫所有代碼。

這種身份驗證有兩種合適的方法:

  • 作為Decorator:如果一些視圖(但不是很多)需要這樣的檢查,那么最好為它編寫一個裝飾器(像@Jingo寫的那樣)
  • 作為中間件:如果該檢查需要由所有(或許多)視圖完成,而不是使用裝飾器,編寫中間件是更好的解決方案。

示例中間件可以是:

ALLOWED_IP_BLOCKS = [......]

class NeedToLoginMiddleware(object):
    def process_request(self, request):
        ip = request.META['REMOTE_ADDR']
        if not ip in ALLOWED_IP_BLOCKS: #ip check
            if not request.user.is_authenticated(): #if ip check failed, make authentication check
                return HttpResponseRedirect(...)
        return None
  • 你可以使用列表進行ip檢查,或者像@Jingo提到的那樣使用正則表達式進行ip檢查。
  • 如果您使用的是django身份驗證且REMOTE_ADDR不在ALLOWED_IP_BLOCKS列表中,則可以使用is_authenticated檢查相關用戶是否已登錄。 但是,為了在自定義中間件中使用is_authenticated ,您的自定義中間件必須放在 AuthenticationMiddleware 之后 ,因為request.user是在該級別上設置的。

     MIDDLEWARE_CLASSES = ( ... 'django.contrib.auth.middleware.AuthenticationMiddleware', 'path.to.my.NeedToLoginMiddleware', ... ) 
    • 如果一些視圖不需要此身份驗證,那么您可以創建例外URL列表並從request.path獲取請求URL並檢查請求URL是否需要ip檢查/身份驗證。

有關自定義中間件類的更多信息

您還可以為此目的編寫一個小裝飾器:

def login_by_ip(view_func):
    def authorize(request, *args, **kwargs):
        user_ip = request.META['REMOTE_ADDR']
        for ip in allowedIps.allowedIps:
            authenticated_by_ip = re.compile(ip).match(user_ip)
            if authenticated_by_ip:
                return view_func(request, authenticated_by_ip, *args, **kwargs)
        return HttpResponseRedirect('/redirect/path/')
    return authorize

allowedIps在我的例子中是一個文件(allowedIps.py),它存儲一個元組中允許的IP的正則表達式,如下所示:

allowedIps = ('^XXX\.XXX\..+\..+$','^XXX\.XXX\.XXX\..+$', '^XXX\.XXX\.XXX\.XXX$')

希望這可以幫助或提出一個想法。 注意:如果將authenticated_by_ip返回到裝飾視圖,則視圖必須接受該參數,如果不需要,也可以省略它。 您還可以更精確地定義正則表達式,以僅接受最多三個數字。

沒有必要為您編寫的用例編寫身份驗證后端。 在中間件層中編寫基於IP的調度程序可能就足夠了

如果您的應用程序的URL匹配,則process_request應檢查經過身份驗證的django用戶並將該用戶與白名單進行匹配。

你可以嘗試這個裝飾。 我測試了它的工作正常:

allowedIps = ['129.0.0.1', '127.0.0.1']
def allow_by_ip(view_func):
    def authorize(request, *args, **kwargs):
        user_ip = request.META['REMOTE_ADDR']
        for ip in allowedIps:
            if ip==user_ip:
                return view_func(request, *args, **kwargs)
        return HttpResponse('Invalid Ip Access!')
    return authorize

IMO,如果它是一個小型的非性能關鍵站點,那么用Django解決這個問題就好了。

最好使用Apache或Nginx服務來保護未經授權的用戶。 例如,在Nginx中,我在我的站點配置中有這些行:

include allowed_ips.conf;
deny all;
error_page 403 forbidden.html;

allowed_ips.conf在/ etc / nginx中,看起來像這樣:

allow 110.222.333.222;  # J Bloggs (sys admin)
allow 777.222.0.0/16;   # Government owned
...

我相信這更好,因為相對緩慢的Django進程永遠不會被阻塞的IP觸及。 如果出於性能或安全原因阻止機器人或其他國家/地區范圍,這一點很重要。

def login_by_id(request):
    ip = request.META['REMOTE_ADDR']
    try: UserProfile.objects.get(allow_ip=ip)
    except UserProfile.DoesNotExist: return HttpResponseRedirect('././')
    else:
        # auth here

您需要在UserProfile模型中使用allow_ip ,這樣可以節省注冊或更改編輯用戶頁面

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM