Django Rest Framework - использование аутентификации сессии и токена
Я пытаюсь заставить это работать, но не знаю, возможно ли это. Так должно быть.
Я разработал веб-приложение, используя Django
+ Rest-Framework
+ jQuery
, и я хочу иметь внешнее приложение, чтобы потреблять то же самое REST
API, используя JWT Tokens
для аутентификации.
Мой текущий конфиг такой.
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_RENDERER_CLASS': [
'rest_framework.renderers.JSONRenderer',
]
}
SIMPLE_JWT = {
'AUTH_HEADER_TYPES': ('Bearer',),
}
views.py
class ListFileView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, *args, **kwargs):
user = request.user
if user:
obj = Foo.objects.filter(owner=user)
serializer = FooSerializer(obj, many=True)
data = serializer.data
return Response(data, status=status.HTTP_200_OK)
return Response({'detail': 'You have no access to files.'}, status=status.HTTP_400_BAD_REQUEST)
Сложность в том, что когда я использую:
permission_classes = (IsAuthenticated,)
Я могу выполнить ajax
звонки из внешнего приложения (с использованием действующего JWT
токен), но jQuery
вызовы из приложения (с аутентифицированным пользователем) завершаются неудачно с:
{"detail":"Authentication credentials were not provided."}
И с другой стороны, если я использую autentication_classes
вместо permission_classes
:
authentication_classes = (SessionAuthentication, BasicAuthentication)
Я могу выполнять вызовы AJAX из веб-приложения, используя jQuery
, но внешние вызовы терпят неудачу с тем же 403
ошибка.
Я попытался использовать оба, как это:
class ListFileView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication)
permission_classes = (IsAuthenticated,)
def get(self, request, *args, **kwargs):
...
но внешние вызовы также отклоняются.
Возможно ли иметь эти два типа Auth
работать вместе в одном и том же class
посмотреть, или я должен разделить на две конечные точки?
РЕДАКТИРОВАТЬ
Пример звонков из приложения с jQuery
:
<script type="text/javascript">
function loadTblDocs() {
$("#tbl-docs > tbody").empty();
$.ajaxSetup({
headers: { "X-CSRFToken": '{{csrf_token}}' }
});
$.ajax({
type: 'GET',
contentType: "application/json; charset=utf-8",
url: "/api/list/",
dataType: "json",
success: function (data) {
console.log(data);
}
});
};
</script>
И внешне через VBA
код:
Set web = CreateObject("WinHttp.WinHttpRequest.5.1")
web.Open "GET", "/api/list/", False
web.SetRequestHeader "Authorization", "Bearer <JWT_TOKEN_HERE>"
web.Send
1 ответ
Я не смог точно определить, что происходит в вашем случае, потому что поведение в трех случаях, которыми вы поделились, кажется непоследовательным, но я просто объясню, как определяется аутентификация и авторизация в DRF, это может помочь вам понять проблема вышла.
Вы должны быть в состоянии использовать два класса аутентификации без проблем. С DRF аутентификация работает так:
При каждом запросе DRF просматривает предоставленные классы аутентификации в порядке их определения. Для каждого класса есть 3 случая:
- Если он может аутентифицировать запрос с текущим классом, DRF устанавливает request.user. С этого момента этот запрос аутентифицируется.
- Если учетные данные для аутентификации отсутствуют, DRF пропускает этот класс
- Если учетные данные аутентификации присутствуют, но недействительны, например, недействительный токен JWT в заголовке авторизации, DRF вызывает исключение и возвращает ответ 403.
Представления DRF, как правило, используют классы аутентификации, определенные в файле настроек, но если вы предоставите их в представлении, настройки будут переопределены.
Авторизация вступает в игру, когда вы добавляете allow_classes к своим представлениям. license_classes контролируют доступ к вашим представлениям, поэтому при добавлении IsAuthenticated к классам разрешений представления DRF отклоняет запрос с ответом 403, если вы пытаетесь получить доступ к этому представлению без аутентифицированного пользователя.
Таким образом, в вашем первоначальном случае ваш внутренний ajax-запрос в этом случае терпит неудачу и предполагает, что в вашем сеансе запроса нет аутентифицированных пользовательских данных. Я не знаю, что может быть причиной этого, может быть, вы не обновляете сеанс запроса в представлении входа в систему (метод входа в django должен делать это автоматически).
Во втором случае вы удаляете allow_classes из представления, поэтому представление будет обслуживать запрос независимо от того, есть ли в запросе аутентифицированный пользователь или нет. Таким образом, ожидается, что ваш внутренний ajax-запрос будет выполнен успешно, но я не знаю, почему ваш внешний запрос не выполняется в этом случае.
В вашем третьем случае, с точки зрения вашего внутреннего ajax-запроса, сценарий выглядит так же, как и в первом случае, поэтому я не знаю, почему ваш внутренний ajax-запрос выполняется в этом случае успешно, но не в первом. Здесь ожидается сбой внешнего запроса, потому что вы добавили класс разрешения IsAuthenticated в представление, но не включили JWTAuthentication в authentic_classes, поэтому ваш запрос не может быть аутентифицирован с помощью вашего токена JWT здесь.