13

随着客户端 API 的更新,HTTPBasicAuthication 方法已替换为 OAuth2Bearer授权标头。

使用旧 API,我将执行以下操作:

NSURLCredential *credential = [NSURLCredential credentialWithUser:self.account.username 
                                                         password:self.account.token 
                                                      persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *space = [[NSURLProtectionSpace alloc] initWithHost:kAPIHost
                                                                    port:443
                                                                protocol:NSURLProtectionSpaceHTTPS
                                                                   realm:@"my-api"
                                                    authenticationMethod:NSURLAuthenticationMethodHTTPBasic];

但这不适用于Bearer标题。

现在通常我会像这样添加我自己的标题:

NSString *authorization = [NSString stringWithFormat:@"Bearer %@",self.account.token];
[urlRequest setValue:authorization forHTTPHeaderField:@"Authorization"];

但这个解决方案的问题是 API 将大部分调用重定向到其他 URL,这与安全性有关。重定向后NSURLRequest,授权标头从请求中删除,并且由于我无法将 Bearer 方法添加到NSURLCredentialStorage重定向后,它无法再进行身份验证。

什么是好的解决方案?我只能想抓住重定向并修改它,NSURLRequest所以它确实包含Bearer标题。但是怎么做?

4

3 回答 3

16

好吧,经过大量研究,我发现我只需要在NSURLRequest重定向呼叫时替换。

没有我希望的那么好,但确实有效。

我使用AFNetworking并添加了重定向块,然后检查是否Authorization仍然设置了标头,如果没有我创建一个新的NSMutableURLRequest并设置所有属性以匹配旧请求(我知道我可能刚刚创建了一个可变副本):

[requestOperation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {

    if ([request.allHTTPHeaderFields objectForKey:@"Authorization"] != nil) {
        return request;
    }

    NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:request.URL cachePolicy:request.cachePolicy timeoutInterval:request.timeoutInterval];
    NSString *authValue = [NSString stringWithFormat:@"Bearer %@", self.account.token];
    [urlRequest setValue:authValue forHTTPHeaderField:@"Authorization"];

    return  urlRequest;

}];
于 2012-08-24T12:46:57.783 回答
4

我正在使用 AFNetworking 库

找到AFHttpClient.m你有一个方法

- (void)setAuthorizationHeaderWithToken:(NSString *)token {
    [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Token token=\"%@\"", token]];
}

将此方法替换为以下内容,或者如果您需要它以实现向后兼容性,请将其保留为具有不同名称的添加并使用该名称

- (void)setAuthorizationHeaderWithToken:(NSString *)token {
    [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Bearer %@", token]];
}

然后使用 oauth 访问令牌发出请求。(以下是一个GET方法服务)

    NSURL *url = [EFServiceUrlProvider getServiceUrlForMethod:methodName];
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
    [httpClient setAuthorizationHeaderWithToken:@"add your access token here"];

    [httpClient getPath:@"" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString *response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //
    }];

更新


在 matt 编写的 AFNetworking 上使用 Oauth2 客户端

https://github.com/AFNetworking/AFOAuth2Client

于 2012-11-23T13:05:32.717 回答
1

如果您碰巧在 Django REST 框架和路由器中遇到此问题,则该问题可能与 NSUrlRequest 剪切的尾部斜杠有关。如果尾部斜杠被剪裁,那么 django 将不得不重定向您的请求,为避免这种情况,您可以像这样使用 Trailing_slash = True

router = routers.DefaultRouter(trailing_slash=False)

这样,您的授权标头和参数都不会丢失。

希望这可以节省一些时间。

于 2014-03-20T14:52:32.823 回答