Использование CORS и CSRF вместе в приложении Ionic

Я разрабатываю приложение для Android с использованием Ionic Framework, основанного на веб-сайте AngularJS, который я разработал с помощью Jhipster. Поскольку у меня уже есть серверный код, запущенный в моем веб-приложении, я выбираю Ionic для работы в качестве интерфейса и сервера вызовов, когда это необходимо, но у меня есть некоторые проблемы в моей среде разработки.

  • Когда я запускаю свое приложение с использованием Ionic, мне нужно использовать CORS для запросов на сервер.
  • Мое веб-приложение было разработано с использованием токена CSRF с Spring Безопасность

Я использую фильтр Apache CORS, настроенный таким образом:

private void initCORSFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) {
    FilterRegistration.Dynamic corsFilter = servletContext.addFilter("cors", new CorsFilter());
    Map<String, String> parameters = new HashMap<>();
    parameters.put("cors.allowed.origins", "http://localhost:3000");
    parameters.put("cors.allowed.headers", "x-auth-token, x-requested-with, Content-Type, Accept, cache-control, x-csrf-token, Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
    parameters.put("cors.allowed.methods", "POST, PUT, GET, DELETE");
    parameters.put("cors.exposed.headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
    parameters.put("cors.support.credentials", "true");
    corsFilter.setInitParameters(parameters);
    corsFilter.addMappingForUrlPatterns(disps, true, "/*");
}

то я использовал angular-csrf-cross-domain плагин, чтобы помочь с кросс-доменными запросами csrf:

.config(function ($urlRouterProvider,csrfCDProvider) {
    $urlRouterProvider.otherwise('/');
    //enable CSRF
    csrfCDProvider.setHeaderName('X-CSRF-TOKEN');
    csrfCDProvider.setCookieName('CSRF-TOKEN');
});

Затем я попробую отправить почтовый запрос на мой локальный сервер:

angular.module('consamiApp')
.factory('Register', function ($resource) {
    //globalURL is https://localhost:8080
    return $resource(globalURL+'api/register', {}, {
    });
});
.
.
.
createAccount: function (account, callback) {
    var cb = callback || angular.noop;

    return Register.save(account,
        function () {
            return cb(account);
        },
        function (err) {
            this.logout();
            return cb(err);
    }.bind(this)).$promise;
}

Однако я получаю это сообщение в консоли firefox:

Запрос на блокировку с перекрестным происхождением: та же самая политика происхождения (политика одинакового происхождения) предотвращает чтение удаленного ресурса в https://localhost:8080/api/register. (Причина: заголовок CORS "Access-Control-Allow-Origin" отсутствует)

НОВАЯ ИНФОРМАЦИЯ

AngularJs делает 2 запроса CORS серверу, когда я отправляю форму, которую я тестирую: ОПЦИИ и POST, результаты запросов 200 и 403 запрещены. Это заголовки двух запросов и ответов:

ОПЦИИ Заголовки запросов:

Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

ОПЦИИ Заголовки ответов:

Access-Control-Allow-Origin: http://localhost:3000
Content-Length: 0
Date: Tue, 30 Jun 2015 22:07:58 GMT
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=485A653AEAC8B8756DD3057BBF7FB862; Path=/; Secure; HttpOnly
CSRF-TOKEN=e8b3396c-63b2-47bf-9ad6-c1454628eb3b; Path=/
X-Application-Context: application:dev:8080
access-control-allow-credentials: true
access-control-allow-headers: origin,access-control-request-headers,x-requested-with,x-csrf-token,content-type,access-control-request-method,cache-control,x-auth-token,accept
access-control-allow-methods: POST
access-control-max-age: 1800

Заголовок запроса POST:

Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: application/json, text/plain, */*
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=utf-8
Referer: http://localhost:3000/
Content-Length: 109
Origin: http://localhost:3000
Cookie: _ga=GA1.1.123103160.1428358695; connect.sid=s%3AwD4KP4WBfhGO0JpFND3LpCzW.augts9fos9NMaZw%2B7XrNuilgaM8ocwSxaEUeDlIaVJ4; JSESSIONID=93200F4F4AFCEB28F10B130841808621
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

Заголовки ответов POST:

Content-Type: application/json;charset=UTF-8
Date: Tue, 30 Jun 2015 22:07:58 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked

Есть ли что-то, чего я не заметил? Ionic официальный блог говорит, что я не должен беспокоиться о проблеме CORS при развертывании приложения, но, по крайней мере, для тестов, мне действительно нужно решить эти проблемы. Не могли бы вы дать мне какие-либо варианты?

Ответ 1

Когда я редактировал вопрос и видел заголовок ответа OPTIONS с предложением HttpOnly, я начал полагать, что проблема заключалась в самоподписанном сертификате, который я использую в среде разработки.

Set-Cookie: JSESSIONID = 485A653AEAC8B8756DD3057BBF7FB862; Path =/; Безопасный; HttpOnly

Итак, я решил отключить протокол https на веб-сервере, и он работал правильно. Благодарим за помощь.

Ответ 2

Установили ли вы и настроили список плагинов Cordova, который является обязательным для запроса CORS, поскольку Cordova 5.0.0

установить его:

cordova plugin add cordova-plugin-whitelist

настроить config.xml

Вы можете сохранить свою текущую настройку с * или изменить для более ограничительных правил

добавить политику html на index.html, вы также должны добавить политику. Чтобы разрешить все, вот оно:

 <meta http-equiv="Content-Security-Policy" content="default-src *;
 style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'
 'unsafe-eval'"

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

cordova plugins 

Вы увидите в нем белый символ cordova-plugin.

Во-вторых, вам может понадобиться добавить withCredentials к вашим запросам $http (и, следовательно, $resource):

  .config(function($httpProvider) {
        $httpProvider.defaults.withCredentials = true;
    });

Ответ 3

Спецификация CORS - это все или ничего. Он поддерживает только *, нулевой или точный домен: http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

Я не думаю, что вы можете указать номера портов в качестве значения.