CFHTTPAuthenticationCreateFromResponse无法分析响应 我正在编写IOS代码,用HTTPS代理服务器进行身份验证,并需要使用核心基础API来构造代理授权标头。但是,我在尝试构建有效的CFHTTPAuthenticationRef对象时被阻止
收到带有“Proxy Authenticate:Basic realm=example.com”头的“407 Proxy authentication required”响应后,我将调用CFHTTPAuthenticationCreateFromResponse。这将返回无效的CFHTTPAuthenticationRef对象;错误为-1000,或kCFStreamErrorHTTPAuthenticationTypeUnsupported 从上的非常过时的源代码来看,这一切都可以正常工作。我已经在调试器中验证了一些内部结构,比如_方案,实际上被正确解析,因此我知道我的头值是正确的。很明显,CFHTTPAuthenticationCreateFromResponse中的代码已经更改,但是我不知道我需要做什么才能使它工作 从单步遍历汇编代码来看,这似乎与缺少URL有关。没有公共API向响应添加URL,事实上Basic和Digest auth不需要URL,这很奇怪 我在OSX Mavericks、iOS 7模拟器和iOS 8模拟器上观察到了这一点。我把它归结为一个简单的复制函数,粘贴在下面。我还尝试使用测试代理服务器和CFReadStream,从CFReadStreamCopyPropertyrequestStream、kCFStreamPropertyHTTPResponseHeader创建响应,但毫无效果,这可能会将URL与响应对象关联CFHTTPAuthenticationCreateFromResponse无法分析响应 我正在编写IOS代码,用HTTPS代理服务器进行身份验证,并需要使用核心基础API来构造代理授权标头。但是,我在尝试构建有效的CFHTTPAuthenticationRef对象时被阻止,ios,cocoa,http-authentication,http-proxy,cfnetwork,Ios,Cocoa,Http Authentication,Http Proxy,Cfnetwork,收到带有“Proxy Authenticate:Basic realm=example.com”头的“407 Proxy authentication required”响应后,我将调用CFHTTPAuthenticationCreateFromResponse。这将返回无效的CFHTTPAuthenticationRef对象;错误为-1000,或kCFStreamErrorHTTPAuthenticationTypeUnsupported 从上的非常过时的源代码来看,这一切都可以正常工作。我已
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)
你遇到了,但有点不同的味道。
问题是,CFHTTPAuthenticationCreateFromResponse仅适用于从CFHTTPStream获取的响应。
我找到了一个解决办法
公开私有API这将导致您无法通过Apple review
// 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);