标签:
一、简要概述
OAuth2.0是OAuth协议的下一版本,时常用于移动客户端的开发,是一种比较安全的机制。在OAuth 2.0中,server将发行一个短有效期的access token和长生命期的refresh token。这将允许客户端无需用户再次操作而获取一个新的access token,并且也限制了access token的有效期。即当sever发送的access token过期之后,客户端会调用方法,将access token和refresh token发送给服务端,服务端将会返回新的access token和refresh token。
二、应用场景
用户登录后,服务端会发行一个有效时间的access token,同时也会发行一个长生命期的refresh token。用户在进行其他网络请求时,会把access token加入请求体中(并不需要加入refresh token)。如果在请求过程中,access token过期,返回相应的状态码。这时就回调用一个回调方法,在回调方法体中将原来的access token和refresh token发送给服务端,获取新的access token和refresh token。然后把新的access token加入刚才的请求体中,重新加载网络请求。
限定access token的有效时间,只是为了提高安全性。access token过期后重新获取并重新加载请求这一操作,用户是察觉不到的。这种机制在微信、QQ、微博等客户端中尤为常见。
三、实例代码
(1)此类继承了AFNetworking中的AFHTTPSessionManager类,并重写了里面的方法。
NetWorkCallBack.h:
1 #import <Foundation/Foundation.h>
2 #import <AFNetworking.h>
3 @interface NetWorkCallBack : AFHTTPSessionManager
4
5 @end
NetWorkCallBack.m:
1 #import "NetWorkCallBack.h"
2 #import <SSKeychain.h>
3 @implementation NetWorkCallBack
4
5 - (NSURLSessionDataTask *)dataTaskWithRequest:(NSMutableURLRequest *)urlRequest completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))originalCompletionHandler{
6
7 //create a completion block that wraps the original
8 void (^authFailBlock)(NSURLResponse *response, id responseObject, NSError *error) = ^(NSURLResponse *response, id responseObject, NSError *error)
9 {
10 NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
11 if([httpResponse statusCode] == 401){
12
13 //如果access token过期,返回错误,调用此block
14 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
15
16 //调用refreshAccesstoken方法,刷新access token。
17 [self refreshAccessToken:^(AFHTTPRequestOperation *operation) {
18 //存取新的access token,此处我使用了KeyChain存取
19 NSDictionary *headerInfo = operation.response.allHeaderFields;
20 NSString *newAccessToken = [headerInfo objectForKey:@"access-token"];
21 NSString *newRefreshToken = [headerInfo objectForKey:@"refresh-token"];
22 [SSKeychain deletePasswordForService:@"<key>" account:@"access-token"];
23 [SSKeychain deletePasswordForService:@"<key>" account:@"refresh-token"];
24 [SSKeychain setPassword:newAccessToken forService:@"<key>" account:@"access-token"];
25 [SSKeychain setPassword:newRefreshToken forService:@"<key>" account:@"refresh-token"];
26
27 //将新的access token加入到原来的请求体中,重新发送请求。
28 [urlRequest setValue:newAccessToken forHTTPHeaderField:@"access-token"];
29
30 NSURLSessionDataTask *originalTask = [super dataTaskWithRequest:urlRequest completionHandler:originalCompletionHandler];
31 [originalTask resume];
32 }];
33 });
34 }else{
35 NSLog(@"no auth error");
36 originalCompletionHandler(response, responseObject, error);
37 }
38 };
39
40 NSURLSessionDataTask *stask = [super dataTaskWithRequest:urlRequest completionHandler:authFailBlock];
41
42 return stask;
43
44 };
45
46
47 /*
48 *获取新的token的方法。如何获取可以自定义,我这里用了AFNetWorking的AFHTTPRequestOperation类
49 */
50 -(void)refreshAccessToken:(void(^)(AFHTTPRequestOperation *responseObject))refresh{
51 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:@"<yourURL>"];
52
53 [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
54
55 //将原来的access token和refresh token发送给服务器,以获取新的token
56 NSString *accessToken = [SSKeychain passwordForService:@"<key>" account:@"access-token"];
57 NSString *refreshToken = [SSKeychain passwordForService:@"<key>" account:@"refresh-token"];
58
59 [request setValue:accessToken forHTTPHeaderField:@"access-token"];
60 [request setValue:refreshToken forHTTPHeaderField:@"refresh-token"];
61
62 //执行网络方法
63 AFHTTPRequestOperation *httpRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
64 [httpRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation * operation, id responseObject) {
65 refresh(operation);
66 } failure:^(AFHTTPRequestOperation * operation, NSError * error) {
67 refresh(operation);
68 }];
69 [httpRequestOperation start];
70 }
71 @end
iOS实现OAuth2.0中刷新access token并重新请求数据操作
标签:
原文地址:http://www.cnblogs.com/zhoubo-log/p/5010662.html