使用AFNetWorking 实现以Basic Authentication方式获取access-token
由于服务器端对于调用API获取数据接口进行了限制,需要在调用API之前获取一个access-token,所以需要在iOS里实现获取这个access-token的功能。 服务器端是在ASP.NET中基于Owin OAuth使用Client Credentials Grand方式发放Token,具体的实现细节可以参考这篇博客。
根据服务端提供的测试代码,如下:
private async Task GetAccessToken(string grantType, string userName = null, string password = null) { var parameters = new Dictionary<string, string>(); parameters.Add("client_id", "1234"); parameters.Add("client_secret", "5678"); var clientId = "1234"; var clientSecret = "5678"; var parameters = new Dictionary<string, string>(); parameters.Add("grant_type", grantType); if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password)) { parameters.Add("username", userName); parameters.Add("password", password); } _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(clientId + ":" + clientSecret)) ); var response = await _httpClient.PostAsync("/token", new FormUrlEncodedContent(parameters)); var responseValue = await response.Content.ReadAsStringAsync(); }
通过上面的代码就可以看出在客户端需要做下面几件事情:
1、对client_id和client_secret进行Base64String编码,在iOS里有专门对NSString进行Base64编码的库,具体请参见NSData+Base64。
2、将grant_type为"client_credentials"作为参数Post给服务器地址;
3、最后需要注意的是AFNetWorking 实现Basic 验证的时候,传值的时候注意Basic后面有一个空格,然后设置Content-Type为"application/x-www-form-urlencoded;charset=UTF-8"。这样就可以拿到access_token。代码如下:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSString *client_id = @"1234"; NSString *client_secret = @"5678"; NSString *authStr = [NSString stringWithFormat:@"%@:%@",client_id,client_secret]; NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding]; NSString *authValue = [NSString stringWithFormat:@"Basic %@",[authData base64EncodedStringWithOptions:0]]; [manager.requestSerializer setValue:authValue forHTTPHeaderField:@"Authorization"]; [manager.requestSerializer setValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; NSDictionary *params = @{@"grant_type":@"client_credentials"}; [manager POST:@"http://api.cnblogs.com/token" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"JSON: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", [error description]); }];
这样就完成了本次场景的需求。实验以Basic 验证方式获取access_token。这样拿到服务端的授权以后就可以调用公开的API列表啦。