Django Rest Framework возвращает 200 OK, даже если запрос на вход имеет неверные учетные данные

Это мой URLS.py:

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^CMS/', include('CMSApp.urls')),
    url(r'^admin/', include(admin.site.urls)),
]

и это CMSApp / urls.py:

from django.conf.urls import url
from django.conf.urls import include
from CMSApp import views

urlpatterns = [
    url(r'^$', views.HomePageView.as_view()),
    url(r'^users$', views.user_list.as_view()),
    url(r'^users/(?P<pk>[0-9]+)$', views.user_detail.as_view()),
    url(r'^api-auth/', include('rest_framework.urls',
                                   namespace='rest_framework')),
]

My HomePageView обслуживает эту страницу home.html:

<h3>Register</h3>
<form ng-submit="ctrl.add()" name="myForm">
    <label>Username</label>
    <input type="text" name="uname" ng-model="ctrl.user.username" required> 
    <label>Password</label>
    <input type="password" name="pwd" ng-model="ctrl.user.password" required>
    <label>Email</label>
    <input type="email" name="mail" ng-model="ctrl.user.email" required> 
    <input type="submit" value="Register"> 
</form>

<h3>Login</h3>
<form ng-submit="ctrl.loginUser()" name="myLoginForm">
    <label>Username</label>
    <input type="text" name="uname" ng-model="ctrl.user.username" required> 
    <label>Password</label>
    <input type="password" name="pwd" ng-model="ctrl.user.password" required>
    <input type="submit" value="Login"> 
</form>

<script>
angular.module("notesApp", [])
    .config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.xsrfCookieName = 'csrftoken';
        $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
    }])

    .controller("MainCtrl", ["$http", function($http) {
    var self = this;
    self.users = {};
    var fetchUsers = function() {
        return $http.get("/CMS/users").then(function(response) { // get list of existing users
            self.users = response.data;
        }, function(errResponse) {
        console.error("Error while fetching users.");
        });
    };

    self.loginUser = function() {
        $http.post("/CMS/api-auth/login/", self.user)
        .error(function(data, status, headers, config) {
            console.log(data);
         })
        .then(fetchUsers);

        console.log("Success Login with ", self.user);
    };
    }]);
</script>

Когда я регистрирую пользователя, который уже существует, Django возвращает ошибку 400 Bad Request, что хорошо, потому что я использую AngularJS во внешнем интерфейсе для обработки кода состояния 400.

Проблема в том, что когда я пытаюсь войти в систему с неправильным именем пользователя и паролем (имя пользователя, которое не существует, или имя пользователя и пароль, которые не совпадают), Django возвращает код состояния 200 OK, поэтому я не могу отследить проблему с помощью AngularJS на веб-интерфейсе. Есть идеи, почему Django возвращает 200 OK, когда я пытаюсь войти в систему с неправильным именем пользователя и паролем? Как заставить Django возвращать 400 при вводе неверного имени пользователя / пароля?

Изменить: это был мой исходный пост: Django Rest Framework + AngularJS не выполняет вход в систему и не выдает ошибки, а charlietfl прокомментировал это, сказав, что« что касается обработки ошибок ajax. Если вход в систему не удается .... использование истинной методологии REST отправит обратно 401 status, который затем запустит ваш обработчик ошибок ajax ", поэтому я не хочу, чтобы 200 OK при сбое входа в систему.


person SilentDev    schedule 24.07.2015    source источник
comment
Какие у вас настройки DRF для аутентификации и разрешений?   -  person Mark Galloway    schedule 24.07.2015
comment
@MarkGalloway Я использую встроенную аутентификацию Django Rest Framework и ее настройки по умолчанию (я сделал из импорта django.conf.urls include, а затем добавил url (r '^ api-auth /', include ('rest_framework.urls' , namespace = 'rest_framework')) на мой urls.py). Я использую любые настройки по умолчанию (я ничего не менял, я просто использую тот URL, о котором здесь говорится: django-rest-framework.org/tutorial/   -  person SilentDev    schedule 24.07.2015


Ответы (1)


Первое, что нужно понять, это то, что Django по умолчанию не применяет аутентификацию ... вы можете использовать модуль аутентификации для регистрации пользователей и их аутентификации, но вы должны явно защищать свои представления. Приложение аутентификации предоставляет вам только API-интерфейсы, на самом деле оно ничего не защищает, если вы не используете эти API.

Любое представление, которое явно не проверено на аутентификацию, будет открыто для всех.

Конечно, администратор требует, чтобы вы вошли в систему, но это потому, что авторы приложения администратора включили проверки в свой код ...

В Django REST Framework есть собственные проверки для этого, поэтому требуется очень мало кода, вам просто нужно настроить каждое представление (см. Документацию):

http://www.django-rest-framework.org/api-guide/authentication/

Для любого другого вида, который вы, возможно, захотите защитить, вам нужно добавить несколько проверок. Декоратор @login_required в вашем представлении - это один из способов сделать это для обычных представлений типов функций. Поскольку вы имеете дело с представлениями на основе классов, посмотрите документацию Django здесь:

https://docs.djangoproject.com/en/1.8/topics/class-based-views/intro/#mixins-that-wrap-as-view

Другой вариант проверки статуса входа в систему - использовать класс промежуточного программного обеспечения. Это то, что я делаю в своей нынешней системе, поскольку почти все на нашем сайте требует, чтобы пользователь был авторизован. Итак, в классе промежуточного программного обеспечения мы проверяем, есть ли request.user.is_anonymous. Если да, то есть лишь небольшое подмножество страниц, к которым они могут получить доступ, и если они не обращаются к этим страницам, мы перенаправляем их для входа в систему. Промежуточное программное обеспечение запускается перед любым представлением, чтобы покрыть весь сайт.

Хорошо, теперь, когда я понимаю, что вы действительно хотите войти в систему с помощью запроса ajax, а не просто проверять их доступ ... и вы хотите контролировать, какой ответ возвращается, тогда я предлагаю реализовать свое собственное представление для входа в систему услуга. Что-то вроде:

class LoginView(View):
    def get(self, request, *args, **kwargs):
        user = auth.authenticate(
            username=request.GET.get('username'),
            password=request.GET.get('password'))

        # return whatever you want on failure
        if not user or not user.is_active:
            return HttpResponse(status=500)

        auth.login(request, user)
        return HttpResponse('OK')

Я не тестировал этот код, но он должен быть довольно близок.

person little_birdie    schedule 24.07.2015
comment
@little_bridie, верно, потом я добавлю миксины LoginRequired. Но в настоящее время моя проблема заключается в следующем: 1) если я попытаюсь войти в систему с неправильным именем пользователя / паролем, как AngularJS может определить, что это неверно? Потому что Django возвращает статус 200 OK независимо от того, правильный ли логин или нет. 2) Если мне удается использовать правильное имя пользователя / пароль (передавая имя пользователя и пароль в api-auth / login), Django возвращает код состояния 200 OK, но не перенаправляет пользователя на LOGIN_REDIRECT_URL. Он только перенаправляет на LOGIN_REDIRECT_URL, если я перехожу к api-auth / login и авторизуюсь оттуда. - person SilentDev; 24.07.2015
comment
Итак, вы делаете запрос ajax куда? Возможно, будет проще написать собственное специальное представление входа в систему для входа в систему с помощью ajax. Примите имя пользователя и пароль в качестве параметров URL, затем используйте модуль auth для их аутентификации .. user = auth.authenticate (username =, password =), затем auth.login (request, user) .. docs: docs.djangoproject.com/en/1.8/topics/auth/default /. Я добавлю это к своему ответу. - person little_birdie; 24.07.2015
comment
В ответ на вопрос, где вы делаете запрос ajax, это мой запрос: $ http.post (/ CMS / api-auth / login /, self.user) - я обновил свое сообщение, чтобы показать свой AunglarJS код. Итак, в основном, я делаю почтовый запрос ajax в CMS / api-auth / login (здесь обсуждается URL-адрес api-auth: django-rest-framework.org/tutorial/). - person SilentDev; 24.07.2015
comment
о, создание моего собственного пользовательского представления для входа в систему кажется хорошей идеей. Я, наверное, так и сделаю. Кстати, есть идеи, почему URL-адрес входа / выхода из системы DRF по умолчанию (/ api-auth /, о котором говорится здесь: django-rest-framework.org/tutorial/) не перенаправляет должным образом после успешный вход в систему (когда URL-адрес api-auth / login вызывается через AJAX)? И как я могу заставить AngularJS / AJAX определить, не удалось ли войти в систему (поскольку DRF возвращает 200 OK, независимо от того, не удалось ли войти в систему или нет)? - person SilentDev; 24.07.2015
comment
Не могу вам помочь. Хотя я использую Django REST Framework, я не вхожу в систему через нее. Когда мы начнем создавать одностраничные приложения, я могу попробовать ... или просто использовать код, который я опубликовал выше, и не оказаться на вашем месте :) - person little_birdie; 24.07.2015