Основной вызов для основного домена JQuery

Я создал бэкэнд REST API с Spring MVC и защищен базовым Auth с помощью Spring Security.

Я хотел бы сделать перекрестный домен ajax-вызов API REST от клиентов Javascript. Я не хочу использовать JSONP, потому что я не хочу ограничиваться вызовами GET. Я использую CORS, и я поставил правильные заголовки на стороне сервера.

Предположим, что мой REST API находится в домене localhost: 8087 и мой клиент на localhost: 8086, который является перекрестным вызовом.

В моем клиенте Javascript я делаю ajax-вызов с помощью jQuery:

<script>
        $.ajax ({
            url: "http://localhost:8087/SpringMVC/users/user1",
            beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic xxxxxxxxxxxx"); },
            success: function(val) { console.log(val); alert("success" + val); },
            error: function(val) { console.log(val); alert("error" + val); }
        });
</script>

Моя проблема в том, что jQuery не отправляет заголовок авторизации в HTTP-запросе, и я не знаю почему. Я не понимаю, потому что я делаю это в методе beforeSend, поэтому он должен быть внутри HTTP-запроса. Результат: у меня ошибка 401.

Когда я пытаюсь использовать script из того же домена localhost: 8087, который больше не является перекрестным доменом, у меня нет проблем.

Как это возможно?

Мой script - это просто тест. Я не собираюсь указывать свое имя пользователя/пароль на стороне клиента. Но я хочу проверить, как делать ajax-вызовы для базового защищенного REST API. Я предполагаю, что мне нужно отправить на сервер стороне, чтобы защитить мое имя пользователя/пароль, REST API отправляет мне cookie, и мне больше не нужно передавать имя пользователя/пароль для моих следующих вызовов ajax в REST API. Я прав?

Я тестировал свой REST API с клиентом Chrome Advanced REST, и он работает так. Для первого запроса мне нужно передать заголовок авторизации. Тогда это не нужно. Должен ли он работать так же, как с моим веб-клиентом javascript? Я намерен использовать Node.JS с Backbone для его создания.

Большое спасибо.

EDIT2. Похоже, что это проблема с браузером CORS. Я добавил метод Access-Control-Allow-Methods для метода OPTIONS на стороне сервера, и он работает в Chrome. У меня есть доступ к ответу JSON без каких-либо ошибок. Но мне все еще нужно использовать заголовок авторизации для следующих запросов. Как сообщить jQuery, чтобы использовать отправленный cookie?

И когда я пытаюсь использовать Firefox 11, у меня нет доступа к ответу json, и у меня есть ошибка:

"NetworkError: 401 Non-Autorisé - http://localhost:8087/SpringMVC/users/user1"

Ответ 1

По-видимому, Chrome и Firefox рассматривают запросы Cross Domain немного по-другому. Перед выполнением запроса кросс-домена они выполняют так называемый запрос preflight с методом HTTP OPTIONS. Разница между Chrome и Firefox заключается в том, что Chrome отправляет также заголовок авторизации с учетными данными, а Firefox - нет.

Затем он остается проблемой конфигурации Spring Security. Мой url/users/* защищен для всех HTTP-методов, включая OPTIONS. В случае Firefox, поскольку заголовок авторизации не отправляется, мой запрос не разрешен. Если я ограничу свой безопасный url/users/* только методом GET, то он отлично работает для Firefox. Поэтому мне пришлось добавить только это в мой конфигуратор безопасности Spring:

<intercept-url pattern="/users/*" access="isAuthenticated()" method="GET"/>

Впоследствии у меня есть выбор: я могу добавить другие методы для защиты в URL-адресе intercept-url, кроме OPTIONS, или я могу ограничить вызов метода HTTP GET в моем MVC-контроллере Spring, который даже будет обрабатывать мои ВАРИАНТЫ вызывают в соответствии с Javadoc. Я выбрал второе решение. Но если кто-то найдет решение заставить Firefox отправлять учетные данные, такие как Chrome, это было бы здорово, и я бы выбрал этот.

Ответ 2

Другим вариантом для сценария конфигурации Spring Security, представленного rico, будет:

<http ... use-expressions="true">
    <intercept-url pattern="/users/*" access="permitAll" method="OPTIONS"/>
    <intercept-url pattern="/users/*" access="isAuthenticated()"/>
    ...
</http>

Запросы HTTP OPTIONS всегда будут проходить через аутентификацию, а любой другой метод HTTP не будет.

Обратите внимание, что атрибут use-expressions XML установлен в true в элементе <http>. Spring Затем система безопасности ожидает, что атрибуты access элементов <intercept-url> будут содержать Spring выражения EL, например allowAll и isAuthenticated().