OAuth 2承载授权标头

时间:2012-08-23 12:13:41

标签: ios nsurlconnection oauth-2.0 nsurlrequest

通过更新客户端的API,HTTPBasicAuthication方法已替换为OAuth2 Bearer授权标头。

使用旧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后,将从请求中删除Authorization标头,因为我无法将Bearer方法添加到NSURLCredentialStorage,因此在重定向后无法再对其进行身份验证。

什么是好的解决方案?我只能考虑捕获重定向并修改NSURLRequest,因此它包含Bearer标头。但是如何?

3 个答案:

答案 0 :(得分:15)

经过大量研究后,我发现在调用重定向时我只需要替换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;

}];

答案 1 :(得分:4)

我正在使用AFNetworking Library

找到 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

答案 2 :(得分:1)

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

router = routers.DefaultRouter(trailing_slash=False)

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

希望这能节省一些时间。