vertx应用程序中的CORS问题不起作用
Posted
技术标签:
【中文标题】vertx应用程序中的CORS问题不起作用【英文标题】:CORS issue in vertx Application not working 【发布时间】:2016-12-24 02:08:18 【问题描述】:我的 Vertx 服务器位于服务器 A 中,客户端位于服务器 B 中。当我尝试访问 vertx 服务器时,出现 CORS 错误。我添加了一些服务器端代码来处理 CORS 问题,但它不起作用。我们是否需要在客户端添加一些标头。我在这里想念什么?谁能帮忙
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 中的 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();
【问题讨论】:
你看到***.com/questions/33124625/…的问题了吗? @Karol 我试过了,但它会抛出错误。失败:WebSocket 握手期间出错:意外响应代码:400 WebSocket 与这个 HTTP 请求有什么关系? :) 【参考方案1】:这是因为在定义路线时顺序很重要。 只需在 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());
【讨论】:
如果您在服务器上设置了“Access-Control-Allow-Credentials”,那么您不应该在客户端中删除 withCredentials。 ***.com/questions/24687313/… 你的建议有帮助,我已经发布了我的答案。【参考方案2】:我遇到了同样的问题,终于能够解决它。您需要向CorsHandler.create("Regex String Here")
提供一个有效的正则表达式字符串。因此,如果您想通过 CORS 处理允许任何协议:主机:端口,也就是“*”,您可以使用。
router.route().handler(CorsHandler.create(".*.") //note the "." surrounding "*"
如果您想要对允许的协议:主机:端口进行细粒度控制,您可以灵活地使用正则表达式字符串。示例:来自 localhost 和任何端口的 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+"))
【讨论】:
我已经完成了。不需要添加 .allowedHeader("Access-Control-Allow-Method") .allowedHeader("Access-Control-Allow-Origin") .allowedHeader("Access-Control-Allow-Credentials")【参考方案3】:通过在路由器处理程序中将 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();
【讨论】:
为什么要添加 .allowedHeader("Access-Control-Allow-Method") .allowedHeader("Access-Control-Allow-Origin") .allowedHeader("Access-Control-Allow-Credentials" ) => 因为 allowedHeader() 是浏览器在将 HTTP 请求标头从源域发送到主机域之前用来检查 HTTP 请求标头的方法。当我阅读您的代码时,我感到很困惑【参考方案4】:我为此写了一个答案,因为由于我的 cors 问题的另一个性质,这些解决方案都没有帮助。
问题: 在 Chrome 浏览器中(在 Firefox 中没有问题)我得到了随机的 cors 错误。 cors 请求的一部分(飞行前 OPTIONS 请求)总是很好,但是第二个,无论是 GET、POST 等随机失败,并出现标准浏览器的 cors 错误(访问从“源”获取“已被阻止”通过 CORS 策略:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明的响应满足您的需求,请将请求的模式设置为“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);
整个 http 服务器的 AND:
private HttpServer server;
server.exceptionHandler(ex ->
LOGGER.error("Http server exception handler.", ex);
);
然后在 cors 错误期间,我收到错误消息:io.netty.handler.codec.TooLongFrameException:HTTP 标头大于 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>
希望对您有所帮助!
【讨论】:
【参考方案5】:如果您的客户端连接到服务器,只需在
中添加您的客户端地址.putHeader("Access-Control-Allow-Origin", "*")
(而不是 *)
因此,您将能够从浏览器发送请求 withCredentials
。
【讨论】:
我已经实施了您的建议,并根据它更新了问题。请看一看。以上是关于vertx应用程序中的CORS问题不起作用的主要内容,如果未能解决你的问题,请参考以下文章