iOS實現OAuth2.0中刷新access token並重新請求數據操作


一、簡要概述

  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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM