Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 我可以使用NSURLCredentialStorage进行HTTP基本身份验证吗?_Objective C_Cocoa_Http_Authentication_Https - Fatal编程技术网

Objective c 我可以使用NSURLCredentialStorage进行HTTP基本身份验证吗?

Objective c 我可以使用NSURLCredentialStorage进行HTTP基本身份验证吗?,objective-c,cocoa,http,authentication,https,Objective C,Cocoa,Http,Authentication,Https,我有一个cocoa类,我想用它连接到我正在构建的RESTful web服务。我决定在我的PHP后端使用HTTP基本身份验证,就像这样 <?php if (!isset($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="My Realm"'); header('HTTP/1.0 401 Unauthorized'); //Stuff that users will see if t

我有一个cocoa类,我想用它连接到我正在构建的RESTful web服务。我决定在我的PHP后端使用HTTP基本身份验证,就像这样

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    //Stuff that users will see if they click 'Cancel'
    exit;
}
else {
    //Validation Code
    echo "You entered info.";
}
?>

该代码对应于NSURErrorUserCancelledAuthentication。显然,我的代码没有访问NSURLCresidentialstorage,而是取消了身份验证。这可能与PHP HTTP身份验证函数有关吗?这一点我很困惑。

同步
nsurl连接
绝对可以与
NSURLCredentialStorage
一起使用。事情通常是这样的:

  • NSURLConnection
    从服务器请求页面
  • 服务器以401响应进行响应
  • NSURLConnection
    查看它可以从URL收集哪些凭据
  • 如果URL没有提供完整的凭据(用户名和密码),
    NSURLConnection
    也将查阅
    NSURLCredentialStorage
    ,以填补空白
  • 如果尚未确定完整凭据,
    NSURLConnection
    将发送请求凭据的
    -connection:didReceiveAuthenticationChallenge:
    委托方法
  • 如果
    NSURLConnection
    现在终于拥有完整凭据,它将重试原始请求,包括授权数据
  • 通过使用同步连接方法,您只会在步骤5中失去提供自定义身份验证的能力。因此,您可以在URL中预先提供身份验证凭据,或者在发送请求之前将其放入
    NSURLCredentialStorage
    中。e、 g

    NSURLRequest *request =
      [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://user:pass@example.com"]];
    
    [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
    
    或:


    我会注意到Mikeabullahuk的答案是好的,但是如果您使用NSURCredentialPersistencePermanent而不是每个会话,它会将凭据存储在用户密钥链中,以便下次您可以检查NSURCredentialStorage以获取保护空间的默认凭据的非零值,如果您获得非零值,则可以传递中的凭据。我现在正在为我正在编写的delicious.com客户端使用此方法,它在我的测试中运行得非常好。

    在401或其他身份验证挑战不可接受/不可能的情况下,我有时会使用伪CFHTTPMessage生成身份验证行,然后将其复制回NSURLRequest:

    // assume NSString *username and *password exist and NSURLRequest *urlRequest
    // exists and is fully configured except for HTTP Basic Authentication.. 
    
    CFHTTPMessageRef dummyRequest =
        CFHTTPMessageCreateRequest(
            kCFAllocatorDefault,
            CFSTR("GET"),
            (CFURLRef)[urlRequest URL],
            kCFHTTPVersion1_1);
    CFHTTPMessageAddAuthentication(
        dummyRequest,
        nil,
        (CFStringRef)username,
        (CFStringRef)password,
        kCFHTTPAuthenticationSchemeBasic,
        FALSE);
    authorizationString =
        (NSString *)CFHTTPMessageCopyHeaderFieldValue(
            dummyRequest,
            CFSTR("Authorization"));
    CFRelease(dummyRequest);
    
    [urlRequest setValue:authorizationString forHTTPHeaderField:@"Authorization"];
    

    这可能看起来完全是一种奇怪的方式,但它可以容忍用户名/密码不是URL干净的情况,以及NSURLRequest拒绝查询NSURLCresidentialstorage的情况,因为服务器实际上没有发送HTTP 401(例如,它发送一个常规页面).

    将您的凭据设置为保护空间的默认凭据:

    // Permananent, session, whatever.
    NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence: NSURLCredentialPersistencePermanent];
    // Make sure that if the server you are accessing presents a realm, you set it here.
    NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:@"blah.com" port:0 protocol:@"http" realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
    // Store it
    [[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
    

    此时,使用与您设置的保护空间相匹配的保护空间进行质询的任何后续NSURLConnection都将使用此凭据

    我刚才遇到了这个问题。我对ObjectiveC非常陌生,但我想知道是否有任何对象(特别是凭据和保护空间)必须发布。顺便说一句,我在一个异步调用(initWithRequest)上实现了这个方法,但仍然得到了didReceiveAuthenticationChallenge回调。@Bill,protectionSpace确实需要释放,如果在生产代码中使用,就像我使用的+alloc一样。必须释放protectionSpace。alloc将返回retainCount==1的对象,因此在[…setDefaultCredential:…]之后,您应该像[protectionSpace release]一样释放它;NSURLCresidentialstorage对我来说不起作用,但只需在http字符串中加上user:pass作为服务器前缀就行了,非常感谢,这是一个超级简单的解决方案。根据sendSynchronousRequest的苹果文档:“如果下载请求需要身份验证,必须将所需的凭据指定为URL的一部分…“我自己的经验可以证实这一点;也就是说,使用NSURLCRedentialStorage与sendSynchronousRequest不兼容。谢谢!在不需要委托模式的情况下,它特别有用。
    // assume NSString *username and *password exist and NSURLRequest *urlRequest
    // exists and is fully configured except for HTTP Basic Authentication.. 
    
    CFHTTPMessageRef dummyRequest =
        CFHTTPMessageCreateRequest(
            kCFAllocatorDefault,
            CFSTR("GET"),
            (CFURLRef)[urlRequest URL],
            kCFHTTPVersion1_1);
    CFHTTPMessageAddAuthentication(
        dummyRequest,
        nil,
        (CFStringRef)username,
        (CFStringRef)password,
        kCFHTTPAuthenticationSchemeBasic,
        FALSE);
    authorizationString =
        (NSString *)CFHTTPMessageCopyHeaderFieldValue(
            dummyRequest,
            CFSTR("Authorization"));
    CFRelease(dummyRequest);
    
    [urlRequest setValue:authorizationString forHTTPHeaderField:@"Authorization"];
    
    // Permananent, session, whatever.
    NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence: NSURLCredentialPersistencePermanent];
    // Make sure that if the server you are accessing presents a realm, you set it here.
    NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:@"blah.com" port:0 protocol:@"http" realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
    // Store it
    [[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];