CFHTTPAuthenticationCreateFromResponse无法解析响应

时间:2015-02-13 19:39:41

标签: ios cocoa http-authentication http-proxy cfnetwork

我正在编写iOS代码以使用HTTPS代理服务器进行身份验证,并且需要使用Core Foundation API来构建"代理授权"头。但是我阻止了尝试构建有效的CFHTTPAuthenticationRef对象。

收到' 407代理身份验证后需要'使用“代理 - 身份验证”进行响应:基本领域=" example.com"'标题,我正在呼叫CFHTTPAuthenticationCreateFromResponse。这将返回无效的CFHTTPAuthenticationRef对象;错误是-1000,或者kCFStreamErrorHTTPAuthenticationTypeUnsupported。

通过查看http://www.opensource.apple.com/source/CFNetwork/CFNetwork-129.20/HTTP/CFHTTPAuthentication.c中可用的过时源代码,这应该都可以正常工作。我已经在调试器中验证了一些内部结构,比如_schemes,实际上正在被正确解析,所以我知道我的标头值是正确的。很明显,CFHTTPAuthenticationCreateFromResponse中的代码已经发生了变化,但我对于我需要做些什么才能使这项工作感到茫然。

从单步调试程序代码开始,似乎可能与缺少URL有关。没有用于向响应添加URL的公共API,并且Basic和Digest auth不需要的事实是奇怪的。

我在OSX Mavericks,iOS 7模拟器和iOS 8模拟器上观察到了这一点。我把它煮成一个简单的复制功能,贴在下面。我还尝试使用测试代理服务器和CFReadStream,从CFReadStreamCopyProperty(requestStream, kCFStreamPropertyHTTPResponseHeader)创建响应,但无效(可能会将URL与响应对象关联)。

void testCFAuthentication()
{
    Boolean result;
    CFStringRef str;
    const char *rawResponse = "HTTP/1.1 407 Proxy authentication required\r\nProxy-Authenticate: Basic realm=\"example.com\"\r\n\r\n";

    CFHTTPMessageRef responseMessage = NULL;
    responseMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, false);

    // Optional hack, doesn't help
    /*
    CFURLRef url = NULL;
    url = CFURLCreateWithString(NULL, CFSTR("https://example.com/"), NULL);
    _CFHTTPMessageSetResponseURL(responseMessage, url);
    NSLog(@"_CFHTTPMessageSetResponseURL called\n");
    */

    result = CFHTTPMessageAppendBytes(responseMessage, (uint8_t *)rawResponse, strlen(rawResponse));
    NSLog(@"CFHTTPMessageAppendBytes result: %d\n", (int)result);
    NSLog(@"CFHTTPMessageIsHeaderComplete: %d\n", (int)CFHTTPMessageIsHeaderComplete(responseMessage));
    NSLog(@"CFHTTPMessageGetResponseStatusCode: %d\n", (int)CFHTTPMessageGetResponseStatusCode(responseMessage));
    NSLog(@"CFHTTPMessageCopyResponseStatusLine: %s\n", CFStringGetCStringPtr(CFHTTPMessageCopyResponseStatusLine(responseMessage), kCFStringEncodingUTF8));
    NSLog(@"Proxy-Authenticate header value: %s\n", CFStringGetCStringPtr(CFHTTPMessageCopyHeaderFieldValue(responseMessage, CFSTR("Proxy-Authenticate")), kCFStringEncodingUTF8));

    CFHTTPAuthenticationRef auth = NULL;
    auth = CFHTTPAuthenticationCreateFromResponse(NULL, responseMessage);
    NSLog(@"CFHTTPAuthenticationCreateFromResponse:\n"); CFShow(auth);
    if (auth) {
        CFStreamError error = { 0 };
        result = CFHTTPAuthenticationIsValid(auth, &error);
        if (!result) {
            NSLog(@"CFHTTPAuthenticationIsValid: false, error %d (0x%x), domain %ld (0x%lx)\n", error.error, error.error, error.domain, error.domain);
        } else {
            NSLog(@"CFHTTPAuthenticationCopyMethod=%s\n", CFStringGetCStringPtr(CFHTTPAuthenticationCopyMethod(auth), kCFStringEncodingUTF8));
            NSLog(@"authRealm=%s\n", CFStringGetCStringPtr(CFHTTPAuthenticationCopyRealm(auth), kCFStringEncodingUTF8));
        }
    };
}

输出:

2015-02-13 11:01:05.654 CFHTTPMessageAppendBytes result: 1
2015-02-13 11:01:05.655 CFHTTPMessageIsHeaderComplete: 1
2015-02-13 11:01:05.656 CFHTTPMessageGetResponseStatusCode: 407
2015-02-13 11:01:05.657 CFHTTPMessageCopyResponseStatusLine: HTTP/1.1 407 Proxy authentication required
2015-02-13 11:01:05.657 Proxy-Authenticate header value: Basic realm="example.com"
2015-02-13 11:01:05.658 CFHTTPAuthenticationCreateFromResponse:
<CFHTTPAuthentication 0x7fe0d36017f0>{state = Failed; scheme = <undecided>, forProxy = true}
2015-02-13 11:01:05.658 CFHTTPAuthenticationIsValid: false, error -1000 (0xfffffc18), domain 4 (0x4)

1 个答案:

答案 0 :(得分:0)

你遇到same problem as I,但有点不同。 问题是CFHTTPAuthenticationCreateFromResponse仅适用于从CFHTTPStream获取的响应。 我找到了一个解决方案,请参阅my answer

公开私有API(这将导致您无法通过Apple审核)。

// exposing private API for workaround
extern void _CFHTTPMessageSetResponseURL(CFHTTPMessageRef, CFURLRef);

使用此私有API为响应添加添加URL:

_CFHTTPMessageSetResponseURL(responseMessage, 
                             (__bridge CFURLRef)[NSURL URLWithString: "https://example.com/"]);
 auth = CFHTTPAuthenticationCreateFromResponse(NULL, responseMessage);
相关问题