У меня есть базовый API DRF, встроенный в базовое приложение Django, размещенное на Apache 2.4.
В конфигурациях Apache я даю авторизацию / доступ к приложению любому на нашем локальном сервере с дополнительной настройкой базовой аутентификации (для тестирования), чтобы позволить вызову API с внешнего сервера взаимодействовать с некоторыми моделями.
Когда я делаю запрос GET к самому приложению с учетными данными Basic Auth, я получаю ответ 200 с содержимым (мне отказывают, если я не включаю учетные данные). Но когда я делаю запрос GET к конечной точке DRF API, я получаю ответ 401 Unauthorized. 401 предполагает, что ответ не аутентифицируется.
Мой вопрос: почему (или как) вызов API, ориентированного на DRF, должен искать учетные данные для аутентификации в другом месте, чем вызов самого приложения django (если это действительно происходит)?
Конфигурация Apache выглядит так:
DocumentRoot /var/www/html
LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so
WSGIDaemonProcess portal python-home=/home/bio_admin/envs/dj python-path=/var/www/portal/html/bpp
WSGIScriptAlias /portal /var/www/portal/html/bpp/bioworks/wsgi.py process-group=portal
WSGIProcessGroup portal
WSGIPassAuthorization On
Alias /static/ /var/www/portal/html/bpp/static/
<Directory /var/www/portal/html>
AuthType Basic
AuthName "portal"
AuthUserFile "/var/www/portal/html/.htpasswd"
Require user bio_admin
Require ip 74.xxx.xxx.x
</Directory>
DRF-часть файла settings.py выглядит так:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES' : (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
)
}
urls.py для конечной точки api, а также конечной точки, которая возвращает 200 с правильной аутентификацией:
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('projects/', views.ProjectsListView.as_view(), name='projects'),
path('api/projects/', views.projectListAPI.as_view())
]
urlpatterns = format_suffix_patterns(urlpatterns)
views.py класс для рассматриваемого api:
class projectDetailAPI(generics.RetrieveUpdateDestroyAPIView):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
Я передаю учетные данные аутентификации для конечной точки api и обычного URL-адреса просмотра списка. Используя httpie: http -a user:pass http://ip/path/to/url. Единственное, что меняется между запросом GET, который возвращает 200, и запросом GET, который возвращает 401, - это URL-адрес. Закодированные пароли хранятся в файле .htpasswd, показанном в конфигурации Apache. Это может быть очевидно, но я не пытаюсь пройти аутентификацию против пользователя / прохода в любой связанной базе данных, а использую только user: pass в файле .htpasswd.
Когда вы говорите DRF использовать BasicAuthentication, вы говорите DRF выполнить аутентификацию. Наличие rest_framework.authentication.BasicAuthentication означает, что у вас есть Apache, выполняющий аутентификацию, но затем вы хотите аутентифицироваться во второй раз с помощью Django. Вам, вероятно, следует иметь одно или другое. Я бы рекомендовал вместо этого использовать Django, потому что тогда каждый редактор системы может иметь уникальный идентификатор пользователя.
Я понимаю преимущества аутентификации пользователя в django. Однако у приложения нет определенного набора пользователей. Доступ должен предоставляться только запросам, поступающим с IP-адреса локального сервера, за исключением списка аутентифицированных пользователей при вызове извне IP. Похоже, что ограничение по IP - это задача, для которой Apache лучше подходит. Я установил DEFAULT_PERMISSION_CLASSES и DEFAULT_AUTHENTICATION_CLASSES на пустые массивы и получил аутентификацию Apache, спасибо. Удаление настроек REST_FRAMEWORK полностью вернуло ошибку 403.
Идеально. Да, исключение DEFAULT_PERMISSION_CLASSES означает, что нет означает, что у вас есть пустой набор разрешений_classes. Это означает, что настройки, предоставленные DRF, используются вместо того, что вы их заменяете. Удачи!





После того, как DRF получает учетные данные в запросе,
BasicAuthenticationдекодирует их и делегирует аутентификацию серверным процессам, зарегистрированным вsettings.py. Вы определенно передаете имя пользователя и пароль в своем запросе в DRF, и являются ли они правильно закодирован?