代码之家  ›  专栏  ›  技术社区  ›  mazniak

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

  •  19
  • mazniak  · 技术社区  · 17 年前

    我有一个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.";
    }
    ?>
    

    但这有可能吗?我可以非常轻松地进行cookie身份验证,无需NSURLProtectionSpaces或NSURLCredentials或任何身份验证类。另外,是否有任何资源可以让我阅读有关Cocoa身份验证类的更多信息?

    谢谢

    更新:Mikeabullahuk

    Error Domain=NSURLErrorDomain Code=-1012 UserInfo=0x1a5170 "Operation could not be completed. (NSURLErrorDomain error -1012.)"
    

    4 回复  |  直到 17 年前
        1
  •  63
  •   Mike Abdullah    14 年前

    同步的 NSURLConnection NSURLCredentialStorage . 事情通常是这样的:

    1. NSURL连接 从服务器请求页面
    2. 服务器以401响应进行响应
    3. NSURL连接 查看它可以从URL收集哪些凭据
    4. 如果URL有 不 NSURL连接 NSURL认证存储 填补空白
    5. 如果有完整的凭据 尚未确定, 将发送 -connection:didReceiveAuthenticationChallenge: 请求凭据的委托方法
    6. 如果 NSURL连接 现在终于有了完整的凭证,它将重试原始请求,包括授权数据。

    只有 NSURL认证存储 在发送请求之前。例如

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

    NSURLCredential *credential = [NSURLCredential credentialWithUser:@"user"
                                                             password:@"pass"
                                                          persistence:NSURLCredentialPersistenceForSession];
    
    NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
      initWithHost:@"example.com"
      port:0
      protocol:@"http"
      realm:nil
      authenticationMethod:nil];
    
    
    [[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
                                                        forProtectionSpace:protectionSpace];
    [protectionSpace release];
    
    NSURLRequest *request =
      [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]];
    
    [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
    
        2
  •  12
  •   Matt Gallagher    17 年前

    在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(例如,它发送一个常规页面)。

        3
  •  0
  •   Colin Wheeler    17 年前

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

        4
  •  0
  •   quellish    13 年前

    将您的凭据设置为protectionspace的默认凭据:

    // 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都将使用此凭据