Идентификатор аутентификации MVC и Antiforgery с шаблоном SPA Durandal

Некоторые области моего SPA должны быть открыты для всех пользователей, а некоторые области требуют аутентификации. В этих областях это данные, загруженные через AJAX, которые я хочу защитить.

У меня есть служба проверки подлинности (см. ниже), которую я добавляю в качестве зависимости в моем durandal main.js. Услуга называется:

authentication

В моем main.js я звоню

authentication.handleUnauthorizedAjaxRequest(function () {
        app.showMessage('You are not authorized, please login')
        .then(function () {
            router.navigateTo('#/user/login');
        });
    });

Он предупреждает пользователя, что они не авторизованы, и переводит пользователя в режим просмотра/просмотра, где они могут вводить данные и пытаться войти в систему.

Некоторые вопросы, которые приходят на ум при создании этого режима проверки подлинности:

  • Есть ли очевидные проблемы с тем, что я делаю?
  • Является ли это тем, что я "хотел" делать вещи в Дюрандале?
  • Я заново изобретаю колесо? Я не мог видеть ничего подобного в Дюрандале.

Большинство людей, похоже, создают отдельные страницы cshtml; один для входа в систему (если пользователь не аутентифицирован) и обычный index.cshtml Есть ли веские причины для переключения на этот метод?

Мое действие для входа на моем "пользовательском контроллере" на стороне сервера имеет атрибут [ValidateAntiForgeryToken], который мне нужно отправить, а также. У меня также есть служба "antiforgery" (см. Ниже), которую я также добавляю как зависимость в моем файле main.js viewModel затем (также в моем main.js).

antiforgery.addAntiForgeryTokenToAjaxRequests();

Это перехватывает все запросы ajax (вместе с содержимым) и добавляет значение MVC AntiForgeryToken к данным. Кажется, работает так, как я хочу. Пожалуйста, дайте мне знать, есть ли ошибки/ошибки.

Завершить проверку подлинности ниже.

// services/authentication.js
define(function (require) {
    var system = require('durandal/system'),
    app = require('durandal/app'),
    router = require('durandal/plugins/router');

    return {
        handleUnauthorizedAjaxRequests: function (callback) {
            if (!callback) {
                return;
            }
            $(document).ajaxError(function (event, request, options) {
                if (request.status === 401) {
                    callback();
                }
            });
        },

        canLogin: function () {         
            return true;
        },
        login: function (userInfo, navigateToUrl) {
            if (!this.canLogin()) {
                return system.defer(function (dfd) {
                    dfd.reject();
                }).promise();
            }
            var jqxhr = $.post("/user/login", userInfo)
                .done(function (data) {
                    if (data.success == true) {
                        if (!!navigateToUrl) {
                            router.navigateTo(navigateToUrl);
                        } else {
                            return true;
                        }
                    } else {
                        return data;
                    }
                })
                .fail(function (data) {
                    return data;
                });

            return jqxhr;
        }
    };
});

// services/antiforgery.js
define(function (require) {
    var app = require('durandal/app');

    return {
        /*  this intercepts all ajax requests (with content)
            and adds the MVC AntiForgeryToken value to the data
            so that your controller actions with the [ValidateAntiForgeryToken] attribute won't fail

            original idea came from http://stackoverflow.com/info/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken

            to use this

            1) ensure that the following is added to your Durandal Index.cshml
            <form id="__AjaxAntiForgeryForm" action="#" method="post">
                @Html.AntiForgeryToken()
            </form>

            2) in  main.js ensure that this module is added as a dependency

            3) in main.js add the following line
            antiforgery.addAntiForgeryTokenToAjaxRequests();

        */
        addAntiForgeryTokenToAjaxRequests: function () {
            var token = $('#__AjaxAntiForgeryForm     input[name=__RequestVerificationToken]').val();
            if (!token) {
                app.showMessage('ERROR: Authentication Service could not find     __RequestVerificationToken');
            }
            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(token);

            $(document).ajaxSend(function (event, request, options) {
                if (options.hasContent) {
                    options.data = options.data ? [options.data, tokenParam].join("&") :     tokenParam;
                }
            });
        }

    };
});

Ответ 1

Я предпочитаю пропускать токен antiforgery в заголовке. Таким образом, его легко разбирать из запроса на сервере, потому что он не смешивается с вашими данными формы.

Затем я создал настраиваемый фильтр действий, чтобы проверить токен antiforgery.

I создал сообщение уже о том, как это сделать.