簡體   English   中英

如何防止用戶更改 URL<pk> 查看其他提交數據 Django</pk>

[英]How to prevent user changing URL <pk> to see other submission data Django

我是 web 開發世界、Django 以及需要保護 URL 的應用程序的新手,這些用戶更改 foo/bar/ pk以訪問其他用戶數據。

有沒有辦法防止這種情況? 或者是否有一種內置方法可以防止這種情況在 Django 中發生?

例如: foo/bar/22可以更改為foo/bar/14並公開過去的用戶數據。

我已經閱讀了有關該主題的幾個問題的答案,但我運氣不佳,無法清楚,連貫地解釋這一點以及防止這種情況的方法。 我對此不太了解,所以我不知道如何表達這個問題以正確調查它。 請像我 5 歲一樣向我解釋。

有幾種方法可以實現這一目標:

如果您有登錄的概念,只需將URL限制為:

/foo/bar/

並且在代碼中, user=request.user並僅顯示登錄用戶的數據。

另一種方式是:

/foo/bar/{{request.user.id}}/

並在視圖中:

def myview(request, id):
    if id != request.user.id:
        HttpResponseForbidden('You cannot view what is not yours') #Or however you want to handle this

您甚至可以編寫一個中間件 ,將用戶重定向到他們的頁面/foo/bar/userid - 如果沒有登錄,則寫入登錄頁面。

如果你想控制每個對象的訪問,我建議使用django-guardian 以下是配置設置和安裝后的樣子(這是來自django-guardian的文檔 ):

>>> from django.contrib.auth.models import User
>>> boss = User.objects.create(username='Big Boss')
>>> joe = User.objects.create(username='joe')
>>> task = Task.objects.create(summary='Some job', content='', reported_by=boss)
>>> joe.has_perm('view_task', task)
False

如果您不想使用外部庫,也可以在Django的視圖中進行操作

這可能是這樣的:

from django.http import HttpResponseForbidden
from .models import Bar

def view_bar(request, pk):
    bar = Bar.objects.get(pk=pk)
    if not bar.user == request.user:
        return HttpResponseForbidden("You can't view this Bar.")
    # The rest of the view goes here...

只需檢查主鍵檢索的對象是否屬於請求用戶。 在視圖中這將是

if some_object.user == request.user: ...

這要求表示對象的模型具有對User模型的引用。

您將要查看用戶身份驗證和授權,這兩者都是由Django的Auth軟件包提供的 這兩件事之間也存在很大差異。

身份驗證確保某人是他們所說的人。 想一想,登錄。你會得到一個人的全部用戶名和密碼來證明他們是該帳戶的所有者。

授權確保某人能夠訪問他們嘗試訪問的內容。 因此,例如普通用戶將無法僅切換PK。

我在上面提供的鏈接中詳細記錄了授權。 我將從那里開始並運行一些示例代碼。 希望能回答你的問題。 如果沒有,希望它能為您提供足夠的信息,讓您回來詢問更具體的問題。

在django中,當前登錄的用戶在您的視圖中可用作請求對象的屬性user

我們的想法是首先按登錄用戶過濾模型,然后如果有任何結果只顯示這些結果。

如果用戶嘗試訪問不屬於它們的對象,請不要顯示該對象。

處理所有這些的一種方法是使用get_object_or_404快捷方式函數,如果找不到與給定參數匹配的對象,則會引發404錯誤。

使用這個,我們可以將主鍵和當前登錄用戶傳遞給此方法,如果它返回一個對象,這意味着主鍵屬於該用戶,否則它將返回404,就像頁面不存在一樣。

將它插入您的視圖非常簡單:

from django.shortcuts import get_object_or_404, render

from .models import YourModel

def some_view(request, pk=None):
    obj = get_object_or_404(YourModel, pk=pk, user=request.user)
    return render(request, 'details.html', {'object': obj})

現在,如果用戶嘗試訪問具有不屬於它們的pk的鏈接,則會引發404。

在我的項目中,對於多個模型/表,用戶應該只能看到他/她輸入的數據,而不能看到其他用戶輸入的數據。 對於這些模型/表,有一個用戶列。

在列表視圖中,這很容易實現,只需過濾傳遞給model.user = loggged_id.user的列表視圖的查詢集。

但是對於詳細/更新/刪除視圖,在URL中看到PK,可以想象用戶可以編輯URL中的PK並訪問另一個用戶的行/數據。

我正在使用Django基於類的內置視圖。

URL中的PK視圖已經具有LoginRequiredMixin,但這並不能阻止用戶更改URL中的PK。

我的解決方案:“登錄用戶擁有此行Mixin”(DoesLoggedInUserOwnThisRowMixin) - 覆蓋get_object方法並在那里進行測試。

from django.core.exceptions import PermissionDenied

class DoesLoggedInUserOwnThisRowMixin(object):

    def get_object(self):
        '''only allow owner (or superuser) to access the table row'''
        obj = super(DoesLoggedInUserOwnThisRowMixin, self).get_object()
        if self.request.user.is_superuser:
            pass
        elif obj.iUser != self.request.user:
            raise PermissionDenied(
                "Permission Denied -- that's not your record!")
        return obj

瞧!

只需將mixin放在LoginRequiredMixin之后的視圖類定義行上,並使用輸出消息的403.html模板,就可以了。

這是一個反復出現的問題,也意味着一個嚴重的安全漏洞。 我的貢獻是這樣的:

有2個基本方面需要注意。

首先是觀點:

a) 注意向基於函數的視圖添加裝飾器(例如@login_required)或向基於類的 function(例如 LoginRequiredMixin)添加混合。 我發現官方 Django 文檔對此非常有幫助( https://docs.djangoproject.com/en/4.0/topics/auth/default/ )。

b) 在您看來,當您定義要檢索或插入的數據(GET 或 POST 方法)時,必須按該用戶的 ID 過濾用戶的數據。 像這樣的東西:

 def get(self, request, *args, **kwargs):
     self.object = self.get_object(queryset=User.objects.filter(pk=self.request.user.id))
     return super().get(request, *args, **kwargs)

第二個方面是URL:

在 URL 中,您還應該將 URL 限制為視圖中定義的 pk。 像這樣的東西:

path('int:pk/blog-add/', AddBlogView.as_view(), name='blog-add'),

根據我的經驗,這可以防止用戶看到另一個用戶的數據,只需更改 URL 中的數字即可。

希望能幫助到你。

在 django CBV(基於類的視圖)中,您可以通過比較用戶輸入的 pk 和當前登錄的用戶來防止這種情況:

注:我在django 4和python 3.9測試過。

from django.http import HttpResponseForbidden

class UserDetailView(LoginRequiredMixin, DetailView):
    model = your_model

    def dispatch(self, request, *args, **kwargs):
    
        if kwargs.get('pk') != self.request.user.pk:
            return HttpResponseForbidden(_('You do not have permission to     view this page'))
    
        return super().dispatch(request, *args, **kwargs)

暫無
暫無

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

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