vertx 应用程序中的 CORS 问题无法正常工作
CORS issue in vertx Application not working
我的 Vertx 服务器驻留在服务器 A 中,客户端驻留在服务器 B 中。当我尝试访问 Vertx 服务器时,CORS 错误弹出。我添加了一些服务器端代码来处理 CORS 问题,但它不起作用。我们需要在客户端添加一些 header 吗?我在这里错过了什么?谁能帮忙
Vertx 服务器端:
Router router = Router.router(vertx);
router.route().handler(BodyHandler.create());
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("*")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowedHeader("Access-Control-Request-Method")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Headers")
.allowedHeader("Content-Type"));
客户端实现:
function(url, user) {
eventBus = new EventBus(url);
eventBus.onopen = function() {
//Do Something
}
}
更新:
我删除了 header.Now 中的 withCredential 属性我的代码看起来像
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "*")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
但仍然弹出以下错误。你能帮忙吗?
XMLHttpRequest cannot load https://192.168.1.20:7070/Notify/571/rn4nh0r4/xhr_send?t=1471592391921. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'https://login.com' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
更新2:
在
中添加我的客户地址后
.putHeader("Access-Control-Allow-Origin", "*")
我得到以下日志:
XMLHttpRequest cannot LOAD https://192.168.1.20:7070/Notify/773/k3zq1z2z/xhr_send?t=1471601521206. Credentials flag IS 'true', but the 'Access-Control-Allow-Credentials' header IS ''. It must be 'true' TO allow credentials. Origin 'https://login.com' IS therefore NOT allowed access.
我的代码如下:
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "https://login.com")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.putHeader("Access-Control-Allow-Credentials", "true")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
那是因为定义路线时顺序很重要。
只需在 CORS 和 BodyHandler 之间切换:
Router router = Router.router(vertx);
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("*")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowedHeader("Access-Control-Request-Method")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Headers")
.allowedHeader("Content-Type"));
router.route().handler(BodyHandler.create());
如果您的客户端连接到服务器,只需在
中添加您的客户端地址
.putHeader("Access-Control-Allow-Origin", "*")
(而不是 *)
因此您将能够从您的浏览器发送请求withCredentials
。
通过在路由器处理程序中将 withCredential 标志添加为 true 解决了该问题。
我的代码如下
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("https://login.com")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowCredentials(true)
.allowedHeader("Access-Control-Allow-Method")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Content-Type"));
以前只在响应头中设置
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "https://login.com")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.putHeader("Access-Control-Allow-Credentials", "true")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
我也遇到了同样的问题,终于解决了。您需要向 CorsHandler.create("Regex String Here")
提供有效的正则表达式字符串。因此,如果您想通过 CORS 处理允许任何 protocol:host:port,又名“*”,您可以使用。
router.route().handler(CorsHandler.create(".*.") //note the "." surrounding "*"
如果您想要对允许的 protocol:host:port 进行细粒度控制,您可以灵活地使用正则表达式字符串。示例:来自本地主机和任何端口的 http:// 或 https:// 的 CORS 处理将如下所示:
router.route().handler(CorsHandler.create("((http://)|(https://))localhost\:\d+")
.allowedMethod(HttpMethod.GET)
.allowedMethod(HttpMethod.POST)
.allowedMethod(HttpMethod.OPTIONS)
.allowCredentials(true)
.allowedHeader("Access-Control-Allow-Method")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Content-Type")); //makes sure you add other headers expected in the request
要仅允许特定客户端列表,您可以使用 OR 运算符“|”连接在你的正则表达式字符串中。
router.route().handler(CorsHandler.create("http://localhost:8080" | "https://128.32.24.45:\d+"))
我为此写了一个答案,因为由于我的 cors 问题的另一种性质,这些解决方案都没有帮助。
问题:
在 Chrome 浏览器中(在 Firefox 中没有问题)我遇到了随机的 cors 错误。 cors 请求的一部分(pre-flight OPTIONS 请求)总是没问题,但第二部分,无论是 GET、POST 等随机失败,并出现标准浏览器的 cors 错误(Access to fetch at '' from origin '' 已被 CORS 策略阻止:请求的资源上不存在 'Access-Control-Allow-Origin' header。如果不透明响应满足您的需求,请将请求的模式设置为 'no-cors' 以获取资源禁用 CORS。)
api 和前端我有单独的域名。
方案:AWS CloudFront -> S3(静态网站托管)-> ELB -> api(在 ec2 中)
解决方法:
首先,这里是 vertx 中 cors 设置的最终代码,它是有效的:
private void initCors(final Router router) {
final Set<String> allowedHeaders = new HashSet<>();
allowedHeaders.add("x-requested-with");
allowedHeaders.add("Access-Control-Allow-Origin");
allowedHeaders.add("Access-Control-Allow-Methods");
allowedHeaders.add("Access-Control-Allow-Headers");
allowedHeaders.add("Access-Control-Allow-Credentials");
allowedHeaders.add("origin");
allowedHeaders.add("Content-Type");
allowedHeaders.add("accept");
allowedHeaders.add("X-PINGARUNER");
allowedHeaders.add("Authorization");
final Set<HttpMethod> allowedMethods = new HashSet<>();
allowedMethods.add(HttpMethod.GET);
allowedMethods.add(HttpMethod.POST);
allowedMethods.add(HttpMethod.OPTIONS);
allowedMethods.add(HttpMethod.DELETE);
allowedMethods.add(HttpMethod.PATCH);
allowedMethods.add(HttpMethod.PUT);
router.route().handler(CorsHandler.create(".*.")
.allowCredentials(true)
.allowedMethods(allowedMethods)
.allowedHeaders(allowedHeaders));
}
但正如我所说,这还不够。然后我为所有路由启用了日志记录:
private void initApiLogging(Router router) {
router.route().handler(event -> {
String headers = "";
if (event.request().headers() != null
&& !event.request().headers().isEmpty()) {
headers = event.request().headers().entries().toString();
}
LOGGER.debug("{} request to {}, headers: {}",
event.request().method(),
event.request().absoluteURI(),
headers);
event.next();
});
}
router.route().failureHandler(this::exceptionHandler);
AND 对于整个 http 服务器:
private HttpServer server;
server.exceptionHandler(ex -> {
LOGGER.error("Http server exception handler.", ex);
});
然后在 cors 错误期间我收到错误消息:io.netty.handler.codec.TooLongFrameException:HTTP header 大于 8192 字节。
所以增加这个值解决了这个问题。
HttpServerOptions options = new HttpServerOptions();
options.setMaxHeaderSize(1024 * 16);
server = vertx.createHttpServer(options);
注意:如果您也在您的环境中使用 AWS S3,那么不要忘记为其添加 cors 配置:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://you-domain-here.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
希望对您有所帮助!
我的 Vertx 服务器驻留在服务器 A 中,客户端驻留在服务器 B 中。当我尝试访问 Vertx 服务器时,CORS 错误弹出。我添加了一些服务器端代码来处理 CORS 问题,但它不起作用。我们需要在客户端添加一些 header 吗?我在这里错过了什么?谁能帮忙
Vertx 服务器端:
Router router = Router.router(vertx);
router.route().handler(BodyHandler.create());
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("*")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowedHeader("Access-Control-Request-Method")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Headers")
.allowedHeader("Content-Type"));
客户端实现:
function(url, user) {
eventBus = new EventBus(url);
eventBus.onopen = function() {
//Do Something
}
}
更新:
我删除了 header.Now 中的 withCredential 属性我的代码看起来像
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "*")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
但仍然弹出以下错误。你能帮忙吗?
XMLHttpRequest cannot load https://192.168.1.20:7070/Notify/571/rn4nh0r4/xhr_send?t=1471592391921. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'https://login.com' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
更新2: 在
中添加我的客户地址后.putHeader("Access-Control-Allow-Origin", "*")
我得到以下日志:
XMLHttpRequest cannot LOAD https://192.168.1.20:7070/Notify/773/k3zq1z2z/xhr_send?t=1471601521206. Credentials flag IS 'true', but the 'Access-Control-Allow-Credentials' header IS ''. It must be 'true' TO allow credentials. Origin 'https://login.com' IS therefore NOT allowed access.
我的代码如下:
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "https://login.com")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.putHeader("Access-Control-Allow-Credentials", "true")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
那是因为定义路线时顺序很重要。 只需在 CORS 和 BodyHandler 之间切换:
Router router = Router.router(vertx);
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("*")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowedHeader("Access-Control-Request-Method")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Headers")
.allowedHeader("Content-Type"));
router.route().handler(BodyHandler.create());
如果您的客户端连接到服务器,只需在
中添加您的客户端地址.putHeader("Access-Control-Allow-Origin", "*")
(而不是 *)
因此您将能够从您的浏览器发送请求withCredentials
。
通过在路由器处理程序中将 withCredential 标志添加为 true 解决了该问题。
我的代码如下
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("https://login.com")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowCredentials(true)
.allowedHeader("Access-Control-Allow-Method")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Content-Type"));
以前只在响应头中设置
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "https://login.com")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.putHeader("Access-Control-Allow-Credentials", "true")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
我也遇到了同样的问题,终于解决了。您需要向 CorsHandler.create("Regex String Here")
提供有效的正则表达式字符串。因此,如果您想通过 CORS 处理允许任何 protocol:host:port,又名“*”,您可以使用。
router.route().handler(CorsHandler.create(".*.") //note the "." surrounding "*"
如果您想要对允许的 protocol:host:port 进行细粒度控制,您可以灵活地使用正则表达式字符串。示例:来自本地主机和任何端口的 http:// 或 https:// 的 CORS 处理将如下所示:
router.route().handler(CorsHandler.create("((http://)|(https://))localhost\:\d+")
.allowedMethod(HttpMethod.GET)
.allowedMethod(HttpMethod.POST)
.allowedMethod(HttpMethod.OPTIONS)
.allowCredentials(true)
.allowedHeader("Access-Control-Allow-Method")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Content-Type")); //makes sure you add other headers expected in the request
要仅允许特定客户端列表,您可以使用 OR 运算符“|”连接在你的正则表达式字符串中。
router.route().handler(CorsHandler.create("http://localhost:8080" | "https://128.32.24.45:\d+"))
我为此写了一个答案,因为由于我的 cors 问题的另一种性质,这些解决方案都没有帮助。
问题: 在 Chrome 浏览器中(在 Firefox 中没有问题)我遇到了随机的 cors 错误。 cors 请求的一部分(pre-flight OPTIONS 请求)总是没问题,但第二部分,无论是 GET、POST 等随机失败,并出现标准浏览器的 cors 错误(Access to fetch at '' from origin '' 已被 CORS 策略阻止:请求的资源上不存在 'Access-Control-Allow-Origin' header。如果不透明响应满足您的需求,请将请求的模式设置为 'no-cors' 以获取资源禁用 CORS。) api 和前端我有单独的域名。
方案:AWS CloudFront -> S3(静态网站托管)-> ELB -> api(在 ec2 中)
解决方法: 首先,这里是 vertx 中 cors 设置的最终代码,它是有效的:
private void initCors(final Router router) {
final Set<String> allowedHeaders = new HashSet<>();
allowedHeaders.add("x-requested-with");
allowedHeaders.add("Access-Control-Allow-Origin");
allowedHeaders.add("Access-Control-Allow-Methods");
allowedHeaders.add("Access-Control-Allow-Headers");
allowedHeaders.add("Access-Control-Allow-Credentials");
allowedHeaders.add("origin");
allowedHeaders.add("Content-Type");
allowedHeaders.add("accept");
allowedHeaders.add("X-PINGARUNER");
allowedHeaders.add("Authorization");
final Set<HttpMethod> allowedMethods = new HashSet<>();
allowedMethods.add(HttpMethod.GET);
allowedMethods.add(HttpMethod.POST);
allowedMethods.add(HttpMethod.OPTIONS);
allowedMethods.add(HttpMethod.DELETE);
allowedMethods.add(HttpMethod.PATCH);
allowedMethods.add(HttpMethod.PUT);
router.route().handler(CorsHandler.create(".*.")
.allowCredentials(true)
.allowedMethods(allowedMethods)
.allowedHeaders(allowedHeaders));
}
但正如我所说,这还不够。然后我为所有路由启用了日志记录:
private void initApiLogging(Router router) {
router.route().handler(event -> {
String headers = "";
if (event.request().headers() != null
&& !event.request().headers().isEmpty()) {
headers = event.request().headers().entries().toString();
}
LOGGER.debug("{} request to {}, headers: {}",
event.request().method(),
event.request().absoluteURI(),
headers);
event.next();
});
}
router.route().failureHandler(this::exceptionHandler);
AND 对于整个 http 服务器:
private HttpServer server;
server.exceptionHandler(ex -> {
LOGGER.error("Http server exception handler.", ex);
});
然后在 cors 错误期间我收到错误消息:io.netty.handler.codec.TooLongFrameException:HTTP header 大于 8192 字节。 所以增加这个值解决了这个问题。
HttpServerOptions options = new HttpServerOptions();
options.setMaxHeaderSize(1024 * 16);
server = vertx.createHttpServer(options);
注意:如果您也在您的环境中使用 AWS S3,那么不要忘记为其添加 cors 配置:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://you-domain-here.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
希望对您有所帮助!