具有CSRF保护的Java Jersey POST请求

时间:2017-07-11 10:45:37

标签: java spring jersey jersey-2.0 jersey-client

我有一个Spring Boot REST Service,它提供了一些方法。它们受CSRF和用户名/密码基本身份验证(https)保护。

但是,当我尝试执行POST请求时,它失败并显示状态代码403和消息“无法验证提供的CSRF令牌,因为找不到会话”

这是我的客户代码:

    ApiMessage msg = new ApiMessage("Client1", "Key1", "Value1");

    // Set up Basic Authentication
    HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder()
            .nonPreemptive()
            .credentials(ApiUser, ApiUserPassword)
            .build();
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.register(feature);
    Client client = ClientBuilder.newClient(clientConfig);

    // Set up client and target (ApiHost = URI for the request Ressource)
    WebTarget target = client.target(ApiHost);
    WebTarget checkTarget = target.path("check");
    Invocation.Builder invocationBuilder = checkTarget.request(MediaType.APPLICATION_JSON);

    // Do a first request to get the CSRF Header
    Response response = invocationBuilder.post(Entity.entity(msg, MediaType.APPLICATION_JSON));

    if (response.getStatus() == 200) {

        System.out.println("Without CSRF - everything worked. ");

    } else if (response.getStatus() == 403) {

        System.out.println("CSRF Protection: " + response.getStatus() + response.readEntity(String.class));

        // Get CSRF Token out of the response
        Map<String, NewCookie> cookies = response.getCookies();
        String csrf = cookies.get("XSRF-TOKEN").getValue();

        // Add the Token to the header and POST again
        invocationBuilder.header("X-XSRF-TOKEN", csrf);
        response = invocationBuilder.post(Entity.entity(msg, MediaType.APPLICATION_JSON));

        if (response.getStatus() != 200) {
            System.out.println("Error: " + response.getStatus() + response.readEntity(String.class));
        } else {
            System.out.println("With CSRF - everything worked. ");
        }
    } else {
        System.out.println(response.getStatus() + " " + response.readEntity(String.class));
    }

第一个请求以状态403结束,并显示消息“无法验证提供的CSRF令牌,因为未找到您的会话”。 之后,我从响应头中提取CSRF令牌。 但是使用CSRF头的第二个请求失败并出现相同的错误。

在Postman中做同样的事情也可以。

任何想法都是我的错误以及我做错了什么?

1 个答案:

答案 0 :(得分:0)

可能还需要发送一个会话cookie,比如JSESSIONID。得到那个cookie。从NewCookie您创建Cookie并将其添加到请求

NewCookie session = cookies.get("JSESSIONID");
Cookie cookie = session.toCookie();
invocationBuilder.cookie(cookie);

如果它不是JSESSIONID,请检查所有Cookie。它可能是别的东西。