Django REST框架--認證和權限

教程4:認證和權限

目前,咱們的API對誰能夠編輯或刪除代碼段沒有任何限制。咱們想要一些更先進的行爲,以確保:html

  • 代碼段始終與建立者相關聯。
  • 只有身份驗證的用戶能夠建立片斷。
  • 只有片斷的建立者能夠更新或刪除它。
  • 未經身份驗證的請求應具備徹底只讀訪問權限。

將信息添加到咱們的模型

咱們將對咱們的Snippet模型類進行幾回更改首先,咱們添加幾個字段。其中一個字段將用於表示建立代碼段的用戶。另外一個字段將用於存儲代碼的突出顯示的HTML表示。python

將如下兩個字段添加到Snippet模型中models.pysql

owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE) #獲取記錄 刪除級聯 highlighted = models.TextField()

咱們還須要確保在保存模型時,使用pygments代碼突出顯示庫填充突出顯示的字段數據庫

咱們須要一些額外的導入:django

from pygments.lexers import get_lexer_by_name from pygments.formatters.html import HtmlFormatter from pygments import highlight

如今咱們能夠.save()在咱們的模型類中添加一個方法:編程

def save(self, *args, **kwargs): """ Use the `pygments` library to create a highlighted HTML representation of the code snippet. """ lexer = get_lexer_by_name(self.language) linenos = self.linenos and 'table' or False options = self.title and {'title': self.title} or {} formatter = HtmlFormatter(style=self.style, linenos=linenos, full=True, **options) self.highlighted = highlight(self.code, lexer, formatter) super(Snippet, self).save(*args, **kwargs)

完成這些工做後,咱們須要更新咱們的數據庫表。一般咱們將建立一個數據庫遷移,爲了作到這一點,但爲了本教程的目的,咱們只需刪除數據庫並從新開始。api

rm -f tmp.db db.sqlite3 rm -r snippets/migrations python manage.py makemigrations snippets python manage.py migrate

您可能還須要建立幾個不一樣的用戶,以用於測試API。執行此操做的最快方法是使用createsuperuser命令。瀏覽器

python manage.py createsuperuser

爲咱們的用戶模型添加端點

如今咱們有一些用戶可使用,咱們最好將這些用戶的表示添加到咱們的API中。建立一個新的串行器很容易。serializers.py添加:框架

from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all()) class Meta: model = User fields = ('id', 'username', 'snippets')

由於'snippets'用戶模型反向關係,因此在使用ModelSerializer該類時它不會被默認包含,因此咱們須要爲它添加一個顯式字段。ide

咱們還會添加幾個視圖views.py咱們但願只使用只讀視圖爲用戶表示,因此咱們將使用ListAPIViewRetrieveAPIView通用的基於類的意見。

from django.contrib.auth.models import User class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetail(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer

確保也導入UserSerializer

from snippets.serializers import UserSerializer

最後,咱們須要經過從URL conf引用它們將這些視圖添加到API中。將如下內容添加到其中的模式中urls.py

url(r'^users/$', views.UserList.as_view()), url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),

將片斷與用戶關聯

如今,若是咱們建立了一個代碼片斷,那麼就沒有辦法將建立該代碼段的用戶與代碼段實例進行關聯。用戶不是做爲序列化表示的一部分發送的,而是傳入請求的屬性。

咱們處理的方式是覆蓋.perform_create()咱們的代碼片斷視圖上方法,這樣咱們能夠修改實例保存的管理方式,並處理傳入請求或請求的URL中隱含的任何信息。

SnippetList視圖類中,添加如下方法:

def perform_create(self, serializer): serializer.save(owner=self.request.user)

create()咱們的串行器方法如今將被傳遞一個附加'owner'字段,以及請求中驗證的數據。

更新咱們的串行器

如今,這些片斷與建立它們的用戶相關聯,咱們更新咱們SnippetSerializer來反映這一點。將如下字段添加到序列化器定義中serializers.py

owner = serializers.ReadOnlyField(source='owner.username')

注意:確保您還添加'owner',到內部Meta的字段列表

這個領域正在作一些頗有趣的事情。source哪一個屬性參數控制用於填充的字段,而且能夠在對串行化實例的任何屬性點。它也能夠採用上面顯示的點劃線,在這種狀況下,它將以與Django的模板語言同樣的方式遍歷給定的屬性。

咱們添加了字段是類型化ReadOnlyField類,相對於其餘類型的字段,如CharFieldBooleanField等...類型化ReadOnlyField始終是隻讀的,而且將用於序列化表示形式,但不會被用於更新模型他們被反序列化的實例。咱們也能夠CharField(read_only=True)在這裏使用

添加視圖所需的權限

如今,代碼片斷與用戶相關聯,咱們但願確保只有通過身份驗證的用戶才能建立,更新和刪除代碼段。

REST框架包括許多權限類,咱們可使用它來限制哪些人能夠訪問給定的視圖。在這種狀況下,咱們正在尋找的是IsAuthenticatedOrReadOnly,這將確保通過身份驗證的請求得到讀寫訪問權限,未經身份驗證的請求將得到只讀訪問權限。

首先在視圖模塊中添加如下導入

from rest_framework import permissions

接着,下面的屬性添加到SnippetListSnippetDetail視圖類。

permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

添加登陸到Browsable API

若是您打開瀏覽器並瀏覽到可瀏覽的API,那麼您將發現沒法再建立新的代碼段。爲了作到這一點,咱們須要可以以用戶身份登陸。

咱們能夠經過編輯項目級urls.py文件中的URLconf來添加可瀏覽API使用的登陸視圖

在文件頂部添加如下導入:

from django.conf.urls import include

並且,在文件末尾添加一個模式以包括可瀏覽的API的登陸和註銷視圖。

urlpatterns += [ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), ]

r'^api-auth/'模式一部分實際上能夠是您想要使用的任何URL。惟一的限制是包含的URL必須使用'rest_framework'命名空間。在Django 1.9+中,REST框架將設置命名空間,所以您能夠將其刪除。

如今,若是再次打開瀏覽器並刷新頁面,您將在頁面右上方看到一個「登陸」連接。若是您以您以前建立的用戶身份登陸,則能夠再次建立代碼段。

建立了一些代碼片斷後,導航到「/ users /」端點,並注意到每一個用戶的「片斷」字段中,該表示包含與每一個用戶相關聯的代碼段的列表。

對象級權限

咱們但願全部的代碼段均可以被任何人看到,但也要確保只有建立代碼段的用戶才能更新或刪除它。

爲此,咱們將須要建立一個自定義權限。

在片斷應用中,建立一個新文件, permissions.py

from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission): """ Custom permission to only allow owners of an object to edit it. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Write permissions are only allowed to the owner of the snippet. return obj.owner == request.user

如今,咱們能夠經過編輯視圖類中permission_classes屬性將該自定義權限添加到咱們的代碼段實例端點SnippetDetail

permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,)

確保也導入IsOwnerOrReadOnly類。

from snippets.permissions import IsOwnerOrReadOnly

如今,若是再次打開瀏覽器,您會發現若是您以與建立代碼段相同的用戶身份登陸,「DELETE」和「PUT」操做只會顯示在代碼段實例端點上。

使用API​​進行身份驗證

由於咱們如今有一組API的權限,若是咱們要編輯任何代碼片斷,咱們須要驗證咱們的請求。咱們尚未設置任何身份驗證類,因此默認值如今被應用,哪些是SessionAuthenticationBasicAuthentication

當咱們經過Web瀏覽器與API進行交互時,咱們能夠登陸,而後瀏覽器會話將爲請求提供所需的身份驗證。

若是咱們以編程方式與API交互,咱們須要在每一個請求上顯式提供身份驗證憑據。

若是咱們嘗試建立一個沒有驗證的代碼段,咱們會獲得一個錯誤:

http POST http://127.0.0.1:8000/snippets/ code="print 123" { "detail": "Authentication credentials were not provided." }

咱們能夠經過包括咱們以前建立的一個用戶的用戶名和密碼來成功申請。

http -a tom:password123 POST http://127.0.0.1:8000/snippets/ code="print 789" { "id": 1, "owner": "tom", "title": "foo", "code": "print 789", "linenos": false, "language": "python", "style": "friendly" }

概要

咱們如今已經在咱們的Web API上得到了至關精細的權限,併爲系統的用戶和他們建立的代碼段提供了終點。

接下來咱們將介紹如何經過爲突出顯示的片斷建立一個HTML端點來將全部內容結合在一塊兒,並經過使用系統內部關係的超連接來提升API的凝聚力。

相關文章
相關標籤/搜索