Skip to content

RestTemplate Digest Authentication Fails for PUT Requests #35406

@aliciz

Description

@aliciz

version:

  • SpringBoot:3.4.5
  • Spring-web:6.2.6
  • HttpClient5:5.5

I'm trying to use RestTemplate to call a device's HTTP API that requires Digest authentication. My GET requests are working correctly, but the PUT requests are failing.

Here is my code for the RestTemplate configuration:

failing code:

public RestTemplate createClient(String host, int port, String username, String password) {
        // 设置 Digest 用户名密码

        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
                new AuthScope(host, port),
                new UsernamePasswordCredentials(username, password.toCharArray())
        );

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultCredentialsProvider(credentialsProvider)
                .build();

        HttpComponentsClientHttpRequestFactory factory =
                new HttpComponentsClientHttpRequestFactory(httpClient);

        return new RestTemplate(factory);
    }

public static void main(String[] args) {
        ACRemoteControlDoorXML dto = new ACRemoteControlDoorXML();
        dto.setVersion("2.0");
        dto.setCmd("open");
        ACClientManager acClientManager1 = new ACClientManager();
        acClientManager1.createClient("192.168.1.4", 80, "admin", "xxx");
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_XML);
        HttpEntity<ACRemoteControlDoorXML> httpEntity = new HttpEntity<>(dto, httpHeaders);
        // Not working
        ResponseEntity<String> responseEntity = acClientManager1.getClient().exchange("http://192.168.1.4" + remoteControlUrl, HttpMethod.PUT, httpEntity, String.class);

        // Correct code
        String output= acClientManager1.getClient().getForObject("http://192.168.1.4/test", String.class);
}

fail log



2025-09-02 20:06:24.931 DEBUG [main] [-] o.s.web.client.RestTemplate              : HTTP PUT http://192.168.1.4/ISAPI/AccessControl/RemoteControl/door/1
2025-09-02 20:06:24.939 DEBUG [main] [-] i.m.c.u.i.logging.InternalLoggerFactory  : Using SLF4J as the default logging framework
2025-09-02 20:06:24.945 DEBUG [main] [-] o.s.web.client.RestTemplate              : Accept=[text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*]
2025-09-02 20:06:24.973 DEBUG [main] [-] o.s.web.client.RestTemplate              : Writing [RemoteControlDoor{version='2.0', cmd='open'}] as "application/xml"
2025-09-02 20:06:24.976 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ex-0000000001 preparing request execution
2025-09-02 20:06:24.981 DEBUG [main] [-] o.a.h.c.http.impl.classic.ProtocolExec   : ex-0000000001 target auth state: UNCHALLENGED
2025-09-02 20:06:24.982 DEBUG [main] [-] o.a.h.c.http.impl.classic.ProtocolExec   : ex-0000000001 proxy auth state: UNCHALLENGED
2025-09-02 20:06:24.982 DEBUG [main] [-] o.a.h.c.http.impl.classic.ConnectExec    : ex-0000000001 acquiring connection with route {}->[http://192.168.1.4:80]
2025-09-02 20:06:24.982 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ex-0000000001 acquiring endpoint (3 MINUTES)
2025-09-02 20:06:24.985 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ex-0000000001 endpoint lease request (3 MINUTES) [route: {}->[http://192.168.1.4:80]][total available: 0; route allocated: 0 of 5; total allocated: 0 of 25]
2025-09-02 20:06:24.987 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ex-0000000001 endpoint leased [route: {}->[http://192.168.1.4:80]][total available: 0; route allocated: 1 of 5; total allocated: 1 of 25]
2025-09-02 20:06:24.992 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ex-0000000001 acquired ep-0000000001
2025-09-02 20:06:24.992 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ex-0000000001 acquired endpoint ep-0000000001
2025-09-02 20:06:24.992 DEBUG [main] [-] o.a.h.c.http.impl.classic.ConnectExec    : ex-0000000001 opening connection {}->[http://192.168.1.4:80]
2025-09-02 20:06:24.993 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000001 connecting endpoint (null)
2025-09-02 20:06:24.993 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000001 connecting endpoint to http://192.168.1.4:80 (3 MINUTES)
2025-09-02 20:06:24.994 DEBUG [main] [-] .i.i.DefaultHttpClientConnectionOperator : http://192.168.1.4:80 connecting null->/192.168.1.4:80 (3 MINUTES)
2025-09-02 20:06:24.996 DEBUG [main] [-] .i.i.DefaultHttpClientConnectionOperator : http-outgoing-0 http://192.168.1.4:80 connected /192.168.1.14:55538->/192.168.1.4:80
2025-09-02 20:06:24.996 DEBUG [main] [-] h.i.i.DefaultManagedHttpClientConnection : http-outgoing-0 set socket timeout to 3 MINUTES
2025-09-02 20:06:24.996 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000001 connected http-outgoing-0
2025-09-02 20:06:24.996 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000001 endpoint connected
2025-09-02 20:06:24.996 DEBUG [main] [-] o.a.h.c.h.impl.classic.MainClientExec    : ex-0000000001 executing PUT /ISAPI/AccessControl/RemoteControl/door/1
2025-09-02 20:06:24.997 DEBUG [main] [-] o.a.h.c.http.protocol.RequestAddCookies  : ex-0000000001 Cookie spec selected: strict
2025-09-02 20:06:25.001 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000001 start execution ex-0000000001
2025-09-02 20:06:25.002 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000001 executing exchange ex-0000000001 over http-outgoing-0
2025-09-02 20:06:25.002 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> PUT /ISAPI/AccessControl/RemoteControl/door/1 HTTP/1.1
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> Accept: text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> Content-Type: application/xml
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> Accept-Encoding: gzip, x-gzip, deflate
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> Host: 192.168.1.4
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> Transfer-Encoding: chunked
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> Connection: keep-alive
2025-09-02 20:06:25.003 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-0 >> User-Agent: Apache-HttpClient/5.5 (Java/21.0.1)
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "PUT /ISAPI/AccessControl/RemoteControl/door/1 HTTP/1.1[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Accept: text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Content-Type: application/xml[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Accept-Encoding: gzip, x-gzip, deflate[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Host: 192.168.1.4[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Transfer-Encoding: chunked[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Connection: keep-alive[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "User-Agent: Apache-HttpClient/5.5 (Java/21.0.1)[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "[\r][\n]"
2025-09-02 20:06:25.014 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "7a[\r][\n]"
2025-09-02 20:06:25.015 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "<RemoteControlDoor xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0"><cmd xmlns="">open</cmd></RemoteControlDoor>[\r][\n]"
2025-09-02 20:06:25.016 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "0[\r][\n]"
2025-09-02 20:06:25.016 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 >> "[\r][\n]"
2025-09-02 20:06:31.016 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-0 << "end of stream"
2025-09-02 20:06:31.018 DEBUG [main] [-] h.i.i.DefaultManagedHttpClientConnection : http-outgoing-0 close connection IMMEDIATE
2025-09-02 20:06:31.018 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000001 endpoint closed
2025-09-02 20:06:31.018 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000001 discarding endpoint
2025-09-02 20:06:31.018 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000001 releasing endpoint
2025-09-02 20:06:31.018 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000001 connection is not kept alive
2025-09-02 20:06:31.018 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000001 connection released [route: {}->[http://192.168.1.4:80]][total available: 0; route allocated: 0 of 5; total allocated: 0 of 25]
2025-09-02 20:06:31.019 DEBUG [main] [-] o.a.h.c.h.i.c.HttpRequestRetryExec       : ex-0000000001 The target server failed to respond

org.apache.hc.core5.http.NoHttpResponseException: The target server failed to respond
	at org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:333)
	at org.apache.hc.core5.http.impl.io.HttpRequestExecutor.execute(HttpRequestExecutor.java:196)
	at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.lambda$execute$0(InternalExecRuntime.java:236)
	at org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager$InternalConnectionEndpoint.execute(PoolingHttpClientConnectionManager.java:791)
	at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.execute(InternalExecRuntime.java:233)
	at org.apache.hc.client5.http.impl.classic.MainClientExec.execute(MainClientExec.java:120)
	at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
	at org.apache.hc.client5.http.impl.classic.ConnectExec.execute(ConnectExec.java:200)
	at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
	at org.apache.hc.client5.http.impl.classic.ProtocolExec.execute(ProtocolExec.java:195)
	at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
	at org.apache.hc.client5.http.impl.classic.ContentCompressionExec.execute(ContentCompressionExec.java:150)
	at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
	at org.apache.hc.client5.http.impl.classic.HttpRequestRetryExec.execute(HttpRequestRetryExec.java:113)
	at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
	at org.apache.hc.client5.http.impl.classic.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
	at org.apache.hc.client5.http.impl.classic.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:87)
	at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:55)
	at org.apache.hc.client5.http.classic.HttpClient.executeOpen(HttpClient.java:183)
	at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:99)
	at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:71)
	at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:81)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:900)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:801)
	at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:683)
	at com.t30.common.camera.service.impl.ACHikVisionServiceImpl.main(ACHikVisionServiceImpl.java:62)

2025-09-02 20:06:31.021  INFO [main] [-] o.a.h.c.h.i.c.HttpRequestRetryExec       : Recoverable I/O exception (org.apache.hc.core5.http.NoHttpResponseException) caught when processing request to {}->[http://192.168.1.4:80]
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.http.impl.classic.ProtocolExec   : ex-0000000001 target auth state: UNCHALLENGED
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.http.impl.classic.ProtocolExec   : ex-0000000001 proxy auth state: UNCHALLENGED
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.http.impl.classic.ConnectExec    : ex-0000000001 acquiring connection with route {}->[http://192.168.1.4:80]
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ex-0000000001 acquiring endpoint (3 MINUTES)
2025-09-02 20:06:31.021 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ex-0000000001 endpoint lease request (3 MINUTES) [route: {}->[http://192.168.1.4:80]][total available: 0; route allocated: 0 of 5; total allocated: 0 of 25]
2025-09-02 20:06:31.021 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ex-0000000001 endpoint leased [route: {}->[http://192.168.1.4:80]][total available: 0; route allocated: 1 of 5; total allocated: 1 of 25]
2025-09-02 20:06:31.021 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ex-0000000001 acquired ep-0000000002
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ex-0000000001 acquired endpoint ep-0000000002
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.http.impl.classic.ConnectExec    : ex-0000000001 opening connection {}->[http://192.168.1.4:80]
2025-09-02 20:06:31.021 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000002 connecting endpoint (null)
2025-09-02 20:06:31.021 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000002 connecting endpoint to http://192.168.1.4:80 (3 MINUTES)
2025-09-02 20:06:31.021 DEBUG [main] [-] .i.i.DefaultHttpClientConnectionOperator : http://192.168.1.4:80 connecting null->/192.168.1.4:80 (3 MINUTES)
2025-09-02 20:06:31.022 DEBUG [main] [-] .i.i.DefaultHttpClientConnectionOperator : http-outgoing-1 http://192.168.1.4:80 connected /192.168.1.14:63815->/192.168.1.4:80
2025-09-02 20:06:31.022 DEBUG [main] [-] h.i.i.DefaultManagedHttpClientConnection : http-outgoing-1 set socket timeout to 3 MINUTES
2025-09-02 20:06:31.022 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000002 connected http-outgoing-1
2025-09-02 20:06:31.022 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000002 endpoint connected
2025-09-02 20:06:31.022 DEBUG [main] [-] o.a.h.c.h.impl.classic.MainClientExec    : ex-0000000001 executing PUT /ISAPI/AccessControl/RemoteControl/door/1
2025-09-02 20:06:31.022 DEBUG [main] [-] o.a.h.c.http.protocol.RequestAddCookies  : ex-0000000001 Cookie spec selected: strict
2025-09-02 20:06:31.022 DEBUG [main] [-] o.a.h.c.h.i.classic.InternalHttpClient   : ep-0000000002 start execution ex-0000000001
2025-09-02 20:06:31.022 DEBUG [main] [-] h.i.i.PoolingHttpClientConnectionManager : ep-0000000002 executing exchange ex-0000000001 over http-outgoing-1
2025-09-02 20:06:31.022 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> PUT /ISAPI/AccessControl/RemoteControl/door/1 HTTP/1.1
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> Accept: text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> Content-Type: application/xml
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> Accept-Encoding: gzip, x-gzip, deflate
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> Host: 192.168.1.4
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> Transfer-Encoding: chunked
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> Connection: keep-alive
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.headers       : http-outgoing-1 >> User-Agent: Apache-HttpClient/5.5 (Java/21.0.1)
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "PUT /ISAPI/AccessControl/RemoteControl/door/1 HTTP/1.1[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "Accept: text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "Content-Type: application/xml[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "Accept-Encoding: gzip, x-gzip, deflate[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "Host: 192.168.1.4[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "Transfer-Encoding: chunked[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "Connection: keep-alive[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "User-Agent: Apache-HttpClient/5.5 (Java/21.0.1)[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "7a[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "<RemoteControlDoor xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0"><cmd xmlns="">open</cmd></RemoteControlDoor>[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "0[\r][\n]"
2025-09-02 20:06:31.023 DEBUG [main] [-] org.apache.hc.client5.http.wire          : http-outgoing-1 >> "[\r][\n]"

I have confirmed that using a raw HttpClient5 works as expected for the PUT request

Any help would be appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions