ios7 - 使用AFOAuthCredential进行身份验证后无法存储凭据

时间:2014-09-10 16:36:25

标签: ios7 oauth-2.0 afnetworking-2

我使用AFNetworking 2.0 + GROAuth2SessionManager(包括AFOAuthCredential)对我的移动服务器进行身份验证(包括安全框架......)

关于身份验证成功,令牌存储在凭证中:

    - (void)authorizeUser:(NSString *)login password:(NSString *)password onSuccess:(void (^)())success onFailure:(void (^)(NSString *))failure {

    NSURL *url = self.base_url;    

    GROAuth2SessionManager *sessionManager = [GROAuth2SessionManager managerWithBaseURL:url clientID:self.client_key secret:self.client_secret];    
    sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];

    [sessionManager authenticateUsingOAuthWithPath:self.token_path
     login:login
     password:password
     scope:nil
     success:^(AFOAuthCredential *credential) {
         [AFOAuthCredential storeCredential:credential
                             withIdentifier:[url host]];
         self.creds = credential;
         success();
     }
     failure:^(NSError *error) {
         NSLog(@"OAuth client authorization error: %@", error);
         NSDictionary *uinfo = [error userInfo];

         NSHTTPURLResponse *response = [uinfo valueForKey:AFNetworkingOperationFailingURLResponseErrorKey];
         NSInteger status = response.statusCode;
         if (400 <= status && status < 500) {
             [self resignAuthorization];
         }
         failure([uinfo valueForKey:NSLocalizedRecoverySuggestionErrorKey]);
     }];
}

但我在控制台中收到错误:

Unable to fetch credential with identifier "localhost" (Error -25300)

我查看AFOAuthCredential,我可以看到一些关于安全性的方块。
我在应用设置中是否遗漏任何内容以应对它? ...

    #ifdef _SECURITY_SECITEM_H_
NSString * const kAFOAuth2CredentialServiceName = @"AFOAuthCredentialService";

static NSMutableDictionary * AFKeychainQueryDictionaryWithIdentifier(NSString *identifier) {
    NSMutableDictionary *queryDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)kSecClassGenericPassword, kSecClass, kAFOAuth2CredentialServiceName, kSecAttrService, nil];
    [queryDictionary setValue:identifier forKey:(__bridge id)kSecAttrAccount];

    return queryDictionary;
}
#endif

...

#pragma mark Keychain

#ifdef _SECURITY_SECITEM_H_

+ (BOOL)storeCredential:(AFOAuthCredential *)credential withIdentifier:(NSString *)identifier {
    return [self storeCredential:credential withIdentifier:identifier useICloud:NO];
}

+ (BOOL)storeCredential:(AFOAuthCredential *)credential withIdentifier:(NSString *)identifier useICloud:(BOOL)shouldUseICloud {
    id securityAccessibility;
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 43000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090)
    securityAccessibility = (__bridge id)kSecAttrAccessibleWhenUnlocked;
#endif
    return [self storeCredential:credential withIdentifier:identifier withAccessibility:securityAccessibility useICloud:shouldUseICloud];
}

+ (BOOL)storeCredential:(AFOAuthCredential *)credential
         withIdentifier:(NSString *)identifier withAccessibility:(id)securityAccessibility useICloud:(BOOL)shouldUseICloud {
    NSMutableDictionary *queryDictionary = AFKeychainQueryDictionaryWithIdentifier(identifier);

    if (!credential) {
        return [self deleteCredentialWithIdentifier:identifier useICloud:shouldUseICloud];
    }

    NSMutableDictionary *updateDictionary = [NSMutableDictionary dictionary];
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:credential];
    [updateDictionary setObject:data forKey:(__bridge id)kSecValueData];
    if (securityAccessibility) {
        [updateDictionary setObject:securityAccessibility forKey:(__bridge id)kSecAttrAccessible];
    }

    if (shouldUseICloud && &kSecAttrSynchronizable != NULL) {
        [queryDictionary setObject:@YES forKey:(__bridge id)kSecAttrSynchronizable];
        [updateDictionary setObject:@YES forKey:(__bridge id)kSecAttrSynchronizable];
    }

    OSStatus status;
    BOOL exists = ([self retrieveCredentialWithIdentifier:identifier] != nil);

    if (exists) {
        status = SecItemUpdate((__bridge CFDictionaryRef)queryDictionary, (__bridge CFDictionaryRef)updateDictionary);
    } else {
        [queryDictionary addEntriesFromDictionary:updateDictionary];
        status = SecItemAdd((__bridge CFDictionaryRef)queryDictionary, NULL);
    }

    if (status != errSecSuccess) {
        NSLog(@"Unable to %@ credential with identifier \"%@\" (Error %li)", exists ? @"update" : @"add", identifier, (long int)status);
    }

    return (status == errSecSuccess);
}

1 个答案:

答案 0 :(得分:1)

抱歉,再次运行测试后,我意识到它运行正常....第一次获取没有命中标识符...然后存储凭据,后续提取命中存储的标识符...我的错误在模拟器上运行并重置内容....