vertx中的CORS问题应用程序无法正常工作

时间:2016-08-17 12:09:28

标签: javascript java cors vert.x

我的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();

5 个答案:

答案 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>

希望这很有帮助!