【问题标题】:How to Make a Simple POST Request Using Jersey (JAX-RS) to NTLM Authenticated Server如何使用 Jersey (JAX-RS) 向 NTLM Authenticated Server 发出简单的 POST 请求
【发布时间】:2019-04-13 07:58:34
【问题描述】:

我上网查了一下,发现有这样的文章:

NonRepeatableRequestException using jersey and apache httpClient for a REST call

和:

How to send NTLM authenticated post request using jersey?

第二个答案只为 GET 请求提供了解决方案。我正在按如下方式设置我的客户端:

private void init() {
    if (client == null) {
        client = ClientBuilder.newClient(prepareClientConfig());
    }
}

private ClientConfig prepareClientConfig() {
    ClientConfig config = new ClientConfig();
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new NTCredentials(userId, password, null, null));
    config.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credentialsProvider);
    config.connectorProvider(new ApacheConnectorProvider());
    return config;
}

这里是我发出 GET 请求的地方:

@Override
public Response get(String uri, List<HttpUrlParameter> params) throws WebCallException {
    init();
    String url = baseUrl + restUri + apiVersion + uri;
    WebTarget webTarget = client.target(url);
    for (HttpUrlParameter param : params) {
        webTarget = webTarget.queryParam(param.getKey(), param.getValue());
    }
    Response response = webTarget.request(MediaType.APPLICATION_JSON).get();
    return response;
}

HttpUrlParameter 和 WebCallException 类是我定义的。上面的 GET 请求效果很好。然后我尝试 POST 调用:

@Override
public Response post(String uri, Object entity, List<HttpUrlParameter> params) throws WebCallException {
    init();
    String url = baseUrl + restUri + apiVersion + uri;
    WebTarget webTarget = client.target(url);
    for (HttpUrlParameter param : params) {
        webTarget = webTarget.queryParam(param.getKey(), param.getValue());
    }
    Response response = webTarget
              .request(MediaType.APPLICATION_JSON)
              .post(Entity.json(entity));
    return response;
}

我为此特定测试传递的实体非常简单:

import java.util.Date;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public class CrmAccount {

    @JsonProperty("accountid")
    private String accountId;
    @JsonProperty("accountnumber")
    private String accountNumber;
    private String name;
    @JsonProperty("emailaddress1")
    private String emailAddress1;
    @JsonProperty("telephone1")
    private String phoneNumber;
    @JsonProperty("address1_addressid")
    private String address1Id;
    @JsonProperty("address1_line1")
    private String address1Line1;
    @JsonProperty("address1_line2")
    private String address1Line2;
    @JsonProperty("address1_city")
    private String address1City;
    @JsonProperty("address1_stateorprovince")
    private String address1StateOrProvince;
    @JsonProperty("address1_postalcode")
    private String address1PostalCode;
    @JsonProperty("address1_county")
    private String address1Country;

    public CrmAccount() {
        super();
    }

    public String getAccountId() {
        return accountId;
    }

    public void setAccountId(String accountId) {
        this.accountId = accountId;
    }

    public String getAccountNumber() {
        return accountNumber;
    }

    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmailAddress1() {
        return emailAddress1;
    }

    public void setEmailAddress1(String emailAddress1) {
        this.emailAddress1 = emailAddress1;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getAddress1Id() {
        return address1Id;
    }

    public void setAddress1Id(String address1Id) {
        this.address1Id = address1Id;
    }

    public String getAddress1Line1() {
        return address1Line1;
    }

    public void setAddress1Line1(String address1Line1) {
        this.address1Line1 = address1Line1;
    }

    public String getAddress1Line2() {
        return address1Line2;
    }

    public void setAddress1Line2(String address1Line2) {
        this.address1Line2 = address1Line2;
    }

    public String getAddress1City() {
        return address1City;
    }

    public void setAddress1City(String address1City) {
        this.address1City = address1City;
    }

    public String getAddress1StateOrProvince() {
        return address1StateOrProvince;
    }

    public void setAddress1StateOrProvince(String address1StateOrProvince) {
        this.address1StateOrProvince = address1StateOrProvince;
    }

    public String getAddress1PostalCode() {
        return address1PostalCode;
    }

    public void setAddress1PostalCode(String address1PostalCode) {
        this.address1PostalCode = address1PostalCode;
    }

    public String getAddress1Country() {
        return address1Country;
    }

    public void setAddress1Country(String address1Country) {
        this.address1Country = address1Country;
    }
}

我可以毫无问题地通过 Postman 进行 POST 调用,因此我知道调用(在我的 Java 代码之外)工作正常。当我使用 Jersey 进行 POST 调用时,出现以下异常:

javax.ws.rs.ProcessingException: org.apache.http.client.ClientProtocolException
        at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:481)
        at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252)
        at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
        at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
        at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
        at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437)
        at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343)
        at com.harpercollinschristian.integration.util.rest.crm.RestApiClientCrmImpl.post(RestApiClientCrmImpl.java:119)
        at com.harpercollinschristian.integration.service.crm.CrmRestfulApi$4.request(CrmRestfulApi.java:127)
        at com.harpercollinschristian.integration.util.rest.crm.CrmRestApiRequest.exec(CrmRestApiRequest.java:53)
        at com.harpercollinschristian.integration.service.crm.CrmRestfulApi.createAccount(CrmRestfulApi.java:132)
        at com.harpercollinschristian.integration.service.crm.CrmRestfulApiTest.testCreateAccount(CrmRestfulApiTest.java:80)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.apache.http.client.ClientProtocolException
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:71)
        at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:435)
        ... 44 more
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        ... 46 more

在我看来,传递给 post() 方法的 JSON 实体可能设置为只能调用一次的流?我需要为我的所有 POST 和 PATCH 调用发送的 JSON 消息并不长,并且可以使用 FasterXML / Jackson 库轻松地表示为字符串 - 因此我们应该能够轻松地“重复”实体。我知道我可能很明显遗漏了一些东西,但我找不到解决方案。该项目正在使用 Jersey 客户端对其他两个非 Microsoft(因此非 NTLM)服务进行 REST API 调用,因此我需要为这些服务使用 Jersey(换句话说,如果我能提供帮助,我不想将 Jersey 拉出来) .

任何帮助将不胜感激!

【问题讨论】:

    标签: java rest jersey jax-rs ntlm


    【解决方案1】:

    我从我们的 Microsoft CRM 合作伙伴那里收到了一个代码 sn-p,它给出了答案。我们设置需要更新的配置的方法:

    private ClientConfig prepareClientConfig() {
        ClientConfig config = new ClientConfig();
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        final AuthScope ntlmAuthScope = new AuthScope(null, -1, AuthScope.ANY_REALM, "NTLM");
        credentialsProvider.setCredentials(ntlmAuthScope, new NTCredentials(userId, password, null, null));
        config.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credentialsProvider);
        config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
        config.connectorProvider(new ApacheConnectorProvider());
        return config;
    }
    

    注意 REQUEST_ENTITY_PROCESSING 的配置属性 - 设置为 BUFFERED。我相信,这就是我们需要允许实体被缓冲并因此被重用于后续请求(以满足 NTLM 协议)。还有一些其他附加功能(例如特定的 AuthScope)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-29
      • 2023-03-09
      • 2015-04-07
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      相关资源
      最近更新 更多