OAuth 2承载授权标头

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

使用旧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它在重定向后无法再进行身份validation。

什么是好的解决方案? 我只能想到捕获重定向并修改NSURLRequest因此它确实包含了Bearer标头。 但是怎么样?

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

我正在使用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 Client

https://github.com/AFNetworking/AFOAuth2Client

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

 router = routers.DefaultRouter(trailing_slash=False) 

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

希望这能节省一些时间。