如何在swagger + django rest框架中添加token auth?

x33g5p2x  于 2023-08-05  发布在  Go
关注(0)|答案(9)|浏览(198)

我正在使用两个很棒的工具DRFDjango-REST-Swagger,但是我的一些API视图是在令牌身份验证下的。
因此,现在我想在我的API的swagger文档页面中添加测试那些令牌认证API URL的可能性,包括令牌头。我怎么能这么做.
我的类API视图的快照是这样的:

class BookList(APIView):
    """
    List all books, or create a new book.
    """
    authentication_classes = (TokenAuthentication, )
    permission_classes = (IsAuthenticated,)
    ...

字符串
由于Swagger自动检测到很多东西,我希望注意到令牌认证,并在其Web界面中询问我有关令牌或用户ID的信息,但它没有。因此,我通过CURL命令手动测试它...

3bygqnnd

3bygqnnd1#

如果使用令牌身份验证,您可能需要查看this question
基本上,你只需要把它添加到你的settings.py

SWAGGER_SETTINGS = {
    'SECURITY_DEFINITIONS': {
        'api_key': {
            'type': 'apiKey',
            'in': 'header',
            'name': 'Authorization'
        }
    },
}

字符串
在您的Swagger UI页面中,您应该会看到一个 Authorize 按钮。单击该按钮,然后在输入文本字段中输入您的 Authorization 值。

46qrfjad

46qrfjad2#

我回答自己,因为我让它工作。
实际上Swagger设置有一个选项API_key ->

SWAGGER_SETTINGS = {
    "exclude_namespaces": [], # List URL namespaces to ignore
    "api_version": '0.1',  # Specify your API's version
    "api_path": "/",  # Specify the path to your API not a root level
    "enabled_methods": [  # Specify which methods to enable in Swagger UI
        'get',
        'post',
        'put',
        'patch',
        'delete'
    ],
    "api_key": '', # An API key
    "is_authenticated": False,  # Set to True to enforce user authentication,
    "is_superuser": False,  # Set to True to enforce admin only access
}

字符串
对我来说,这不是很清楚,但我只是输入了一个有效的令牌来测试用户,它适用于auth所需的视图:-)

kzipqqlq

kzipqqlq3#

我的问题是,在激活TokenAuthentication后,由于AuthenticationError,我的API URL不再显示在swagger UI中。
对我来说,解决方案是激活Django Rest Framework Settings中的两个authentaction类:
SessionAuthentication->用于Swagger UI
TokenAuthentication->用于其余客户端

REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',
    'rest_framework.authentication.SessionAuthentication'
)

字符串
}

c2e8gylq

c2e8gylq4#

架构视图需要具有AllowAny权限。这允许插件在用户进行身份验证之前查看哪些端点可用。如果设置正确,端点仍应受到保护。示例如下:

@api_view()
@renderer_classes([SwaggerUIRenderer, OpenAPIRenderer, renderers.CoreJSONRenderer])
@authentication_classes((TokenAuthentication, SessionAuthentication))
@permission_classes((AllowAny,))
def schema_view(request):
    generator = schemas.SchemaGenerator(
        title='My API end points',
        patterns=my_urls,
        url="/api/v1/")
    return response.Response(generator.get_schema(request=request))

字符串
最好是删除SessionAuthentication,只使用TokenAuthentication,但这是一个选择的问题,这里我已经删除了它

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication'
)


确保它将'rest_framework.authtoken'添加到您已安装的应用程序中,并将CsrfViewMiddleware从中间件类中删除,因为不再需要它。还有那些趾高气扬的设置

SWAGGER_SETTINGS = {
    'SECURITY_DEFINITIONS': {
        'api_key': {
            'type': 'apiKey',
            'in': 'header',
            'name': 'Authorization'
        }
    },
    'USE_SESSION_AUTH': False,
    'JSON_EDITOR': True,
}


这将使swagger也将令牌填充到所有示例curl命令中,这真的很好。保留会话身份验证似乎会禁用此功能。
swagger授权对话框要求输入需要提供的api_key。似乎不能改善这一点,我会更新这篇文章,如果我这样做。

d5vmydt9

d5vmydt95#

只需添加到您的休息框架设置SessionAuthentication应该在顶部

'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'mymodule.authentication.CustomeAuthentication',
)

字符串

注意:SessionAuthentication将使用您的Django登录会话
CustomeAuthentication将用于API用于真实的用例。

yftpprvb

yftpprvb6#

如果你用django-rest-swagger==2.2.0实现@Melvic Ybanez的答案,但仍然不起作用。降级到django-rest-swagger==2.1.2。按钮授权现在应该工作了。

z9gpfhce

z9gpfhce7#

我设法将Swagger的默认基本身份验证更改为令牌身份验证,但当按下try me按钮时,rest swagger接受任何身份验证,而不考虑有效的令牌。
另外请注意,当我在settings.py中将SessionAuthentication添加到REST_FRAMEWORK时,我的API无法在swagger文档中显示。
django-rest-swagger==2.2.0 djangorestframework==3.7.7
settings.py

INSTALLED_APPS = [
    'rest_framework',
    'rest_framework_swagger',
    'rest_framework.authtoken',
]

REST_FRAMEWORK = {
    # Parser classes priority-wise for Swagger
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
        'rest_framework.parsers.JSONParser',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ) 
}

# SWAGGER SETTINGS
SWAGGER_SETTINGS = {
    'SECURITY_DEFINITIONS': {
        'api_Key': {
            'type': 'apiKey',
            'in': 'header',
            'name': 'Token Authorization'
        }
    },
}

字符串
一些有用的文档https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object

0s0u357o

0s0u357o8#

请使用rest_framework_jwt.authentication.JSONWebTokenAuthentication而不是rest_framework.authentication.TokenAuthentication
我的准则是

REST_FRAMEWORK = {
     'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
         # 'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
        'rest_framework.parsers.JSONParser',
    ),
}

AUTH_USER_MODEL = 'auth.User'

JWT_AUTH = {
    'JWT_ENCODE_HANDLER':
        'rest_framework_jwt.utils.jwt_encode_handler',

    'JWT_DECODE_HANDLER':
        'rest_framework_jwt.utils.jwt_decode_handler',

    'JWT_PAYLOAD_HANDLER':
        'rest_framework_jwt.utils.jwt_payload_handler',

    'JWT_PAYLOAD_GET_USER_ID_HANDLER':
        'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',

    'JWT_RESPONSE_PAYLOAD_HANDLER':
        'rest_framework_jwt.utils.jwt_response_payload_handler',

    'JWT_SECRET_KEY': SECRET_KEY,
    'JWT_ALGORITHM': 'HS256',
    'JWT_VERIFY': True,
    'JWT_VERIFY_EXPIRATION': True,
    'JWT_LEEWAY': 0,
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=86400),
    'JWT_AUDIENCE': None,
    'JWT_ISSUER': None,

    'JWT_ALLOW_REFRESH': True,
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),

    'JWT_AUTH_HEADER_PREFIX': 'Bearer',
}

SWAGGER_SETTINGS = {
    'SHOW_REQUEST_HEADERS': True,
    'SECURITY_DEFINITIONS': {
        'Bearer': {
            'type': 'apiKey',
            'name': 'Authorization',
            'in': 'header'
        }
    },
    'USE_SESSION_AUTH': False,
    'JSON_EDITOR': True,
    'SUPPORTED_SUBMIT_METHODS': [
        'get',
        'post',
        'put',
        'delete',
        'patch'
    ],
}

字符串
我解决了问题。

zaq34kh6

zaq34kh69#

在我的例子中,除了定制(继承)OpenApiAuthenticationExtension,我还必须导入一些api.py(不重要)。基本上这就是我所做的:

  • settings.py*
INSTALLED_APPS = [
    ...
    "django.contrib.admin",
    "django.contrib.auth",
    "mozilla_django_oidc",  # <-- My custom auth backend uses that.
    ...
    "rest_framework",
    ...
    "drf_spectacular",
    ...
]

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "apps.auth.backends.CustomBearerTokenAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": (
        "rest_framework.permissions.AllowAny",
    ),
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

字符串

  • apps.auth.backends:*
from django.contrib.auth.backends import BaseBackend

class CustomBearerTokenAuthentication(BaseBackend):
    """Your custom Bearer Token Authentication Backend."""
    ...

  • apps.auth.scheme:*
from django.utils.translation import gettext_lazy as _
from drf_spectacular.extensions import OpenApiAuthenticationExtension

class CustomTokenScheme(OpenApiAuthenticationExtension):
    target_class = "apps.auth.backends.CustomBearerTokenAuthentication"  # <-- Points to my custom auth backend.
    name = "CustomBearerTokenAuth"

    def get_security_definition(self, auto_schema):
        return {
            "type": "apiKey",
            "in": "header",
            "name": "Authorization",
            "description": _('Token-based authentication with required prefix "%s"')
            % "Bearer",
        }

  • apps.users.API:*
from django.contrib.auth import get_user_model
from rest_framework import mixins, viewsets
from apps.auth.scheme import CreooxTokenScheme  # <-- Only after this import it starts to work!
from .serializers import UserSerializer

User = get_user_model()

class UserViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    serializer_class = UserSerializer

    def get_queryset(self):
        return User.objects.filter(id=self.request.user.id)


最后你得到:


的数据

相关问题