在 Ionic 应用程序中同时使用 CORS 和 CSRF
Using CORS and CSRF together in Ionic app
我正在使用 Ionic Framework based in a AngularJS web site I developed using Jhipster 开发 android 应用程序。因为我的 Web 应用程序中已经有服务器代码 运行ning,所以我选择 Ionic 作为 UI 工作并在需要时调用服务器,但是我的开发环境中遇到了一些问题。
- 因为我 运行 我的应用程序使用 Ionic 服务,我需要使用 CORS 向服务器发出请求。
- 我的 Web 应用程序是使用具有 Spring 安全性
的 CSRF 令牌开发的
我正在使用 Apache CORS filter 这样配置的:
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');
});
然后我尝试向我的本地服务器发送一个 post 请求:
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 控制台中收到此消息:
Cross-origin locked request: The same origin policy (Same Origin Policy) prevents reading the remote resource in https://localhost:8080/api/register. (Reason: CORS heading 'Access-Control-Allow-Origin' is not present)
新信息
AngularJs 当我提交我正在测试的表单时,向服务器发出 2 个 CORS 请求:OPTIONS 和 POST,请求的结果是 200 OK 和 403 Forbidden。这些是 2 个请求和响应中的 headers:
OPTIONS 请求 headers:
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
选项答案headers:
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 请求 Headers:
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 回答Headers:
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's official blog 说我在部署应用程序时不应该担心 CORS 问题,但至少对于测试来说,我确实需要解决这个问题。你能给我任何选择吗?
当我编辑问题并看到带有 HttpOnly 子句的选项响应 header 时,我开始相信问题出在我在开发环境中使用的自签名证书上。
Set-Cookie: JSESSIONID=485A653AEAC8B8756DD3057BBF7FB862; Path=/; Secure; HttpOnly
所以我决定在 Web 服务器中禁用 https 协议并且它工作正常。感谢您的帮助。
CORS 规范是孤注一掷的。它仅支持 *、null 或确切域:http://www.w3.org/TR/cors/#access-control-allow-origin-response-header
我认为您不能指定端口号作为它的值。
您是否安装并配置了自 Cordova 5.0.0
以来 CORS 查询所必需的 cordova plugin whitelist
安装它:
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-whitelist。
其次,您可能需要将 withCredentials
添加到您的 $http
(因此也是 $resource)查询中:
.config(function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
我正在使用 Ionic Framework based in a AngularJS web site I developed using Jhipster 开发 android 应用程序。因为我的 Web 应用程序中已经有服务器代码 运行ning,所以我选择 Ionic 作为 UI 工作并在需要时调用服务器,但是我的开发环境中遇到了一些问题。
- 因为我 运行 我的应用程序使用 Ionic 服务,我需要使用 CORS 向服务器发出请求。
- 我的 Web 应用程序是使用具有 Spring 安全性 的 CSRF 令牌开发的
我正在使用 Apache CORS filter 这样配置的:
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');
});
然后我尝试向我的本地服务器发送一个 post 请求:
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 控制台中收到此消息:
Cross-origin locked request: The same origin policy (Same Origin Policy) prevents reading the remote resource in https://localhost:8080/api/register. (Reason: CORS heading 'Access-Control-Allow-Origin' is not present)
新信息
AngularJs 当我提交我正在测试的表单时,向服务器发出 2 个 CORS 请求:OPTIONS 和 POST,请求的结果是 200 OK 和 403 Forbidden。这些是 2 个请求和响应中的 headers:
OPTIONS 请求 headers:
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
选项答案headers:
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 请求 Headers:
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 回答Headers:
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's official blog 说我在部署应用程序时不应该担心 CORS 问题,但至少对于测试来说,我确实需要解决这个问题。你能给我任何选择吗?
当我编辑问题并看到带有 HttpOnly 子句的选项响应 header 时,我开始相信问题出在我在开发环境中使用的自签名证书上。
Set-Cookie: JSESSIONID=485A653AEAC8B8756DD3057BBF7FB862; Path=/; Secure; HttpOnly
所以我决定在 Web 服务器中禁用 https 协议并且它工作正常。感谢您的帮助。
CORS 规范是孤注一掷的。它仅支持 *、null 或确切域:http://www.w3.org/TR/cors/#access-control-allow-origin-response-header
我认为您不能指定端口号作为它的值。
您是否安装并配置了自 Cordova 5.0.0
以来 CORS 查询所必需的 cordova plugin whitelist安装它:
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-whitelist。
其次,您可能需要将 withCredentials
添加到您的 $http
(因此也是 $resource)查询中:
.config(function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});