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': 'tom@163.com', 'first_name': '', 'last_name': ''}]

	# 没有权限访问
	data = requests.get(url=url)
    text = data.json()  # {'detail': 'Authentication credentials were not provided.'}

if __name__ == '__main__':
	testApi()
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐