OAuth 2.0 Bearer授权头

13

随着客户端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被重定向后,授权头将从请求中删除,由于我无法将Bearer方法添加到NSURLCredentialStorage中,在重定向后无法进行身份验证。

有什么好的解决方案吗?我只能想到捕获重定向并修改NSURLRequest的方式,以便包括Bearer头。但是如何实现呢?

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;

}];

1
你是一个传奇。我遇到了同样的问题,处理重定向解决了它。 - roob

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


不,当请求被重定向时,您将失去令牌。 - rckoenes

1
如果你在使用Django rest framework和路由器时遇到此问题,可能与NSUrlRequest剪切尾随斜杠有关。如果尾随斜杠被剪切,则django将不得不重定向您的请求,为了避免这种情况,您可以像这样使用Trailing_slash = True。
router = routers.DefaultRouter(trailing_slash=False)

那样的话,您的授权标头和参数都不会丢失。 希望这能为某些人节省时间。

1
没有Django,但有ASP.net和PHP也可以实现。一旦发生URL重定向,Authorization就会被清除。这是正常行为,收到403后,可以再次使用Authorization头进行调用。问题在于bearer头不太受支持。 - rckoenes
哇,我们一直在使用Django rest,并且试图弄清楚为什么IOS没有发送Authorization token头,这就是原因,NSURLRequest正在删除尾部斜杠。 - yeahdixon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接