005-Django OAuth Toolkit 身份認證

Django OAuth Toolkit + Django REST Framework 身份認證。
API 官方地址:https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html

1、最小化安裝配置

1)創建一個虛擬環境,並在虛擬環境中安裝以下包:

pip install django-oauth-toolkit djangorestframework

2)將 rest_framework 和 oauth2_provider 添加到 INSTALLED_APPS 設置中:

INSTALLED_APPS = (
    'django.contrib.admin',
    ...
    'oauth2_provider',
    'rest_framework',
)

3)現在需要告訴 Django REST Framework 使用新的身份驗證後端。爲此,需要在 settings.py 的末尾添加以下行:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
    )
}

2、創建 API

2.1 基於函數的 API 視圖

https://django-oauth-toolkit.readthedocs.io/en/latest/views/function_based.html

Django OAuth Toolkit 提供了裝飾器來幫助保護基於功能的視圖:

protected_resource(scopes=None, validator_cls=OAuth2Validator, server_cls=Server)

rw_protected_resource(scopes=None, validator_cls=OAuth2Validator, server_cls=Server)
from oauth2_provider.decorators import protected_resource

@protected_resource()
def my_view(request):
    # ...
    pass
    return HttpResponse(json.dumps({'status':'success'}, ensure_ascii=False))
from oauth2_provider.decorators import rw_protected_resource

@rw_protected_resource()
def my_view(request):
    # If this is a POST, you have to provide 'write' scope to get here...
    # ...
    pass
    return HttpResponse(json.dumps({'status':'success'}, ensure_ascii=False))
# 根路由下添加
path('one/', include('fristapp.urls')),

# fristapp 下添加
path('myo/', my_view),

2.2 基於類的 API 視圖

https://django-oauth-toolkit.readthedocs.io/en/latest/views/class_based.html

Django OAuth Toolkit 提供了一些泛型類,它們對於使用基於類的視圖方法實現 OAuth2 受保護的端點非常有用,繼承類:

ProtectedResourceView						--- ProtectedResourceView(ProtectedResourceMixin, View)
ScopedProtectedResourceView					--- ScopedProtectedResourceView(ScopedResourceMixin, ProtectedResourceView)
ReadWriteScopedResourceView					--- ReadWriteScopedResourceView(ReadWriteScopedResourceMixin, ProtectedResourceView)
class MyEndpoint(ProtectedResourceView):
    """
    A GET endpoint that needs OAuth2 authentication
    """
    def get(self, request, *args, **kwargs):
        return HttpResponse('Hello, World!')
# 根路由下添加
path('two/', include('fristapp.urls')),

# fristapp 下添加
path('myt/', MyEndpoint.as_view()),

2.3 另:權限 API 示例

1)創建序列化類 serializers.py

from django.contrib.auth.models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'email', "first_name", "last_name")

2)定義一個 API
在 app views.py 中創建一個 API:

class MyUserList(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = User.objects.all()
    serializer_class = UserSerializer

class MyUserDetails(generics.RetrieveAPIView):
    permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = User.objects.all()
    serializer_class = UserSerializer

3)在工程根目錄下的 urls.py 中添加:

urlpatterns = [
    path('myapplications/', include('oauth2_provider.urls', namespace='oauth2_provider')),
    path('users/', MyUserList.as_view()),
    path('users/<pk>/', MyUserDetails.as_view(), name='user-detail'),
]

注意:
MyUserDetails 類必須有,對應路由配置 name 的值必須是 user-detail。否則訪問路由 users/ 將不能成功。

2.4 使用身份認證 API 準備工作

1)遷移

python manage.py migrate

2)創建用戶

python manage.py createsuperuser
(tom)

3)啓動項目

python manage.py runserver

4)註冊一個應用程序
訪問下面的鏈接,創建一個應用程序實例:

http://127.0.0.1:8000/myapplications/applications/

在這裏插入圖片描述

  • Name: 僅僅只是一個名稱
  • Client Type: confidential
  • Authorization Grant Type: Resource owner password-based

3、獲取 token 並訪問 API

獲取 token:

import requests

def getToke():
    '''
    獲取token
    :return:
    '''
    url = 'http://127.0.0.1:8000/myapplications/token/'
    params = {
        'grant_type': 'password',
        'username': 'tom',		# user,用戶名
        'password': 'xxxxxx'	# 用戶密碼
    }
    client_id = 'V1fWEMB2usfdafsdfadakRT5S2eQ94q6'
    client_secret = 'adfsdfVYJHnxX7F5NsDr7l9CEKACqdfaercatewewrw'
    auth = HTTPBasicAuth(client_id, client_secret)
    data = requests.post(url=url, data=params, auth=auth)
    text = data.json()
    ''' text 爲字典,內容如下:
    {
        "access_token": "wnS6nkwusdw3sUdzQvH54dfdfw",
        "expires_in": 36000,
        "token_type": "Bearer",
        "scope": "read write groups",
        "refresh_token": "sadfIPmkZywCC45oIIgrJTRDWBKad"
    }
    '''
    return text

訪問 API:

def testApi():
    '''
    訪問API
    :return:
    '''
    dt = getToke()
    url = 'http://127.0.0.1:8000/one/myo/'
    url = 'http://127.0.0.1:8000/two/myt/'
    url = 'http://127.0.0.1:8000/users/'
    headers = {
        "Authorization": f"{dt['token_type']} {dt['access_token']}"
    }
    # 有權限訪問
    data = requests.get(url=url, headers=headers)
    text = data.json()  # [{'username': 'tom', 'email': '[email protected]', 'first_name': '', 'last_name': ''}]

	# 沒有權限訪問
	data = requests.get(url=url)
    text = data.json()  # {'detail': 'Authentication credentials were not provided.'}

if __name__ == '__main__':
	testApi()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章