我的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.
UPDATE2: 在
中添加我的客户地址后.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();
答案 0 :(得分:3)
通过在路由器处理程序中添加withCredential标志来解决问题。
我的代码如下
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();
答案 1 :(得分:3)
我遇到了同样的问题,终于能够解决它。您将需要向CorsHandler.create("Regex String Here")
提供有效的正则表达式字符串。因此,如果您希望通过CORS处理来允许任何protocol:host:port(又名“ *”),则可以使用。
router.route().handler(CorsHandler.create(".*.") //note the "." surrounding "*"
如果要对所允许的protocol:host:port进行细粒度的控制,则可以使用Regex String灵活。示例:从本地主机对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+"))
答案 2 :(得分:2)
这是因为订单在定义路线时很重要。 只需在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());
答案 3 :(得分:2)
如果您的客户端连接到服务器,只需在
中添加您的客户端地址即可.putHeader("Access-Control-Allow-Origin", "*")
(而不是*)
因此,您可以从浏览器发送请求withCredentials
。
答案 4 :(得分:0)
我为此写一个答案,因为由于我的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服务器:
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>
希望这很有帮助!