0

查看更新以获取更新的问题

我将AFNetworking'sAFHTTPClient用于我的应用程序的服务调用。我的服务器使用 HTTP 摘要身份验证进行身份验证。服务调用返回 401 HTTP 错误,WWW-Authenticate其响应中包含标头作为质询,如下所示:

HTTP/1.1 401 
WWW-Authenticate: Digest realm="user@myserver.com",
    qop="auth",
    nonce="059c37d0e654fdba9c606f35ce84741998"
Content-Type: text/html; charset=utf-8

connection:didReceiveAuthenticationChallenge:方法永远不会被调用AFURLConnectionOperation,这是NSURLConnectionDelegate在这种情况下,然后会调用我的块集setAuthenticationChallengeBlock:。相反,我只是得到错误:Error Expected status code in (200-299), got 401在我的AFHTTPRequestOperation失败块中。

据我了解,这些是WWW-AuthenticateHTTP 摘要身份验证标头中唯一必需的字段。这与Wikipedia 上此示例中的响应非常相似。我没有任何实际的响应正文,因为无论如何我都没有向用户显示任何 HTML。这应该重要吗?我没有使用不透明字段,但这应该是可选的。我不支持“auth-int”保护质量。除此之外,我不返回ServerDate标题。是否需要其中任何一个?

我在这里做错了什么?

更新:我现在正在客户端记录响应标头(Apple 没有提供一种简单打印我知道的纯文本响应的好方法)。如上所示的响应是在服务器上记录的。结果NSHTTPURLResponse allHeaders是:

{
    "Alternate-Protocol" = "80:quic";
    "Cache-Control" = private;
    "Content-Type" = "text/html; charset=utf-8";
    Date = "Mon, 09 Sep 2013 20:24:00 GMT";
    Server = "Google Frontend";
    "Transfer-Encoding" = Identity;
    Vary = "Accept-Encoding";
    "Www-Authenticate" = "Digest realm=\"user@myserver.com\",__    qop=\"auth\",__    nonce=\"f36dc1b8abc342d5c1cbad22a533d3868c\"";
}

Server和标Date头实际上包含在服务器以及其他一些标头中。服务器是 Google App Engine。

但问题似乎是我的\r\nCR+LF 出于某种原因被转换__为,这弄乱了标题语法。调查这是为什么...

更新 2:\n使用_. HTTP 要求是使用 CR+LF+SPACE 来分隔标头中的行。所以现在我的问题变成了,如何在我的HttpServletResponse标题字符串中正确包含这个 CR+LF+SPACE 以便正确编码?服务器响应过程中的编码在哪里被更改,导致_我得到的字符?

这是创建响应的服务器代码:

public static void sendUnauthorizedResponse(HttpServletResponse resp, String realm, boolean isStale) throws IOException {
    String s = ",\r\n    ";
    String header = "Digest realm=\"" + realm + "\"" + s + "qop=\"auth\"" + s + "nonce=\"" + createNonce() + "\"";
    if (isStale) {
        header += s + "stale=TRUE";
    }
    resp.setHeader("WWW-Authenticate", header);
    resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    log.info("Sent 401 Unauthorized Response:\n" + resp.toString());
}

最后一行是如上所示记录响应的内容,此时格式正确。

回车\r0x0D 和换行\n0x0A 都被更改为 ASCII 下划线_0x5F。

更新 3:我可以确认这不是客户端问题,但一定是由 Google App Engine 服务器引起的。在海报工具中发布服务调用时,我得到了相同的结果。

更新 4:删除 CR+LF 字符并在一行中包含逗号分隔的属性似乎可行,但根据RFC 2047,行的长度不应超过 75 个字符,现在应该是:

'encoded-word' 的长度不得超过 75 个字符,包括 'charset'、'encoding'、'encoded-text' 和分隔符。如果希望编码的文本多于 75 个字符的“编码字”,则可以使用多个“编码字”(由 CRLF SPACE 分隔)。

虽然对多行​​标题字段的长度没有限制,但包含一个或多个“编码字”的标题字段的每一行被限制为 76 个字符。

所以我仍然需要弄清楚如何正确地将 CR+LF 字符放入我的标题字符串中。

更新 5:因此,似乎HTTP 标头的每行允许的最大字符数取决于服务器,并且可能在数千字节范围内,这对于标头来说应该足够了WWW-Authenticate。但这仍然没有回答为什么我的标题字符串中的“\r\n”字符被转换为“__”的问题。这是 Google App Engine 中的错误吗?很难想象我是唯一一个使用 CR+LF+SPACE 在 HTTP 响应中的新行上分隔我的标头属性的人。

4

0 回答 0