Spring Webflux WebClient:它是不是支持基于摘要的身份验证?

Posted

技术标签:

【中文标题】Spring Webflux WebClient:它是不是支持基于摘要的身份验证?【英文标题】:Spring Webflux WebClient : Does it supports digest based authentication?Spring Webflux WebClient:它是否支持基于摘要的身份验证? 【发布时间】:2018-11-24 17:02:33 【问题描述】:

我刚刚查看了所有 spring 5 文档,但没有发现任何与 WebClient 支持开箱即用的基于摘要的身份验证相关的内容。是否有任何解决方法可以使用 webClient 并仍然调用基于摘要的安全 API?

【问题讨论】:

想详细说明您使用的是哪种摘要式身份验证?您能展示一下示例 HTTP 请求的样子吗? @BrianClozel Digest 身份验证在 RFC2617 中定义,这个问题并不含糊。我赞成这个问题。 @EugèneAdell 我已经相应地回答了 【参考方案1】:

不,目前没有这样的支持。

您可以通过实现org.springframework.web.reactive.function.client.ExchangeFunction 来实现您自己的客户支持。

或者(因为滚动您自己的支持可能很困难),您可以在Spring Security project 上创建一个新问题,并看到社区对此类功能感兴趣。

【讨论】:

@Thom 请再次阅读问题标题和此答案。他们匹配。 链接到产生的问题github.com/spring-projects/spring-framework/issues/24425。【参考方案2】:

下面给出了使用 webClient 获得基于摘要的身份验证的临时解决方案,直到 Spring 社区修复此问题。

public Mono<String> getDigestCallByUserId(String userId) 

    String url = serviceUrl + uri;

    return webClient.get()
        .uri(url)
        .exchange()
        .flatMap(resp -> 

            if (resp.statusCode().equals(HttpStatus.UNAUTHORIZED)) 
                return getSectionsByUserId(userId, resp.headers().header(Constants.HEADER_AUTHENTICATE).get(0), url, uri);
             else 
                return resp.bodyToMono(String.class);
            
        );



public Mono<String> getDigestCallByUserId(String userId, String digestAuthResponse, String url, String uri) 

    return webClient.get()
        .uri(url)
        .header(Constants.HEADER_AUTHORIZATION, getDigestAuthHeader(digestAuthResponse, username, password, uri, HttpMethod.GET.toString()))
        .retrieve()
        .bodyToMono(String.class)
        .log(LOGGER.getName(), Level.SEVERE, SignalType.ON_ERROR, SignalType.CANCEL);




 /**
 * @param values
 * @returns the appended string for the given list of strings
 */
public static String getStringsAppended(String... values) 
    StringBuilder sb = new StringBuilder();
    for (String s : values) 
        sb.append(s);
    
    return sb.toString();


/**
 * @param digestChallenge
 * @param username
 * @param password
 * @param uri
 * @param httpMethod
 * @returns the Digest based authorization header
 */
public static String getDigestAuthHeader(String digestChallenge, String username, String password, String uri,
        String httpMethod) 
    Pattern digestChallengePattern = Pattern.compile(Constants.PATTERN_DIGEST_CHALLENGE);
    Matcher m = digestChallengePattern.matcher(digestChallenge);
    if (m.matches()) 
        String realm = m.group(Constants.DIGEST_AUTH_REALM);
        String qop = m.group(Constants.DIGEST_AUTH_QOP);
        String nonce = m.group(Constants.DIGEST_AUTH_NONCE);
        String clientNonce = DigestScheme.createCnonce();
        String nonceCount = String.format("%08x", 1);

        String ha1 = hash(getStringsAppended(username, Constants.COLON, realm, Constants.COLON, password));
        String ha2 = hash(getStringsAppended(httpMethod, Constants.COLON, uri));
        String response = hash(getStringsAppended(ha1, Constants.COLON, nonce, Constants.COLON, nonceCount,
                Constants.COLON, clientNonce, Constants.COLON, qop, Constants.COLON, ha2));

        return getStringsAppended(Constants.DIGEST, StringUtils.SPACE, Constants.DIGEST_AUTH_USERNAME,
                Constants.EQUAL, Constants.DOUBLE_QUOTE, username, Constants.DOUBLE_QUOTE, Constants.COMMA,
                Constants.DIGEST_AUTH_REALM, Constants.EQUAL, Constants.DOUBLE_QUOTE, realm, Constants.DOUBLE_QUOTE,
                Constants.COMMA, Constants.DIGEST_AUTH_NONCE, Constants.EQUAL, Constants.DOUBLE_QUOTE, nonce,
                Constants.DOUBLE_QUOTE, Constants.COMMA, Constants.DIGEST_AUTH_URI, Constants.EQUAL,
                Constants.DOUBLE_QUOTE, uri, Constants.DOUBLE_QUOTE, Constants.COMMA,
                Constants.DIGEST_AUTH_RESPONSE, Constants.EQUAL, Constants.DOUBLE_QUOTE, response,
                Constants.DOUBLE_QUOTE, Constants.COMMA, Constants.DIGEST_AUTH_QOP, Constants.EQUAL,
                Constants.DOUBLE_QUOTE, qop, Constants.DOUBLE_QUOTE, Constants.COMMA, Constants.DIGEST_AUTH_NC,
                Constants.EQUAL, Constants.DOUBLE_QUOTE, nonceCount, Constants.DOUBLE_QUOTE, Constants.COMMA,
                Constants.DIGEST_AUTH_CNONCE, Constants.EQUAL, Constants.DOUBLE_QUOTE, clientNonce,
                Constants.DOUBLE_QUOTE);
    
    return StringUtils.EMPTY;

【讨论】:

能否提供Constants类的包?我试过搜索这些常量,但找不到 赞赏一个工作示例。此外,getSectionsByUserId 不是摘录的一部分。

以上是关于Spring Webflux WebClient:它是不是支持基于摘要的身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

Spring WebFlux WebClient 弹性和性能

Spring 5 webflux如何在Webclient上设置超时

在 Spring WebFlux webclient 中设置超时

Spring Webflux WebClient

如何模拟 Spring WebFlux WebClient?

如何在 Spring 5 WebFlux WebClient 中设置超时