1
我有一个相当简单的授权/身份验证应用程序,并且需要一些关于如何处理授权生命周期的帮助。下面是它的JIST:iOS:使用NSURLSession进行身份验证和令牌过期
- 用户输入他们的凭据登录服务器用在钥匙串
- 令牌处于“授权”头用于每个后续的URL请求令牌并存储响应(REST调用)
- 令牌最终到期,服务器将与401个状态码
- 回应此时,用户需要通过登录画面重新进行身份验证,所以我们可以得到一个新的令牌,然后重试请求
下面是一些代码,代表我现在可以提出的最好的代码。
static NSString * _authorizationToken;
@implementation MyRestfulModel
+ (id) sharedRestfulModel
{
// singleton model shared across view controllers
static MyRestfulModel * _sharedModel = nil;
@synchronized(self) {
if (_sharedModel == nil)
_sharedModel = [[self init] alloc];
}
return _sharedModel;
}
+ (NSString *) authorizationToken
{
if (!_authorizationToken)
_authorizationToken = @"";
return _authorizationToken;
}
+ (void) setAuthorizationToken: (NSString *token)
{
_authorizationToken = token;
}
-(void) doSomeRestfulCall: (NSString *) restURL
completionHandler: (void (^)(NSData * data)) callback
{
// construct url path and request
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:restURL];
[request setValue:MyRestfulModel.authorizationToken forHTTPHeaderField:@"Authorization"];
[[[NSURLSession sharedSession] dataTaskWithRequest: request
completionHandler:^(NSData *data, NSURLResponse * response, NSError * error) {
NSHTTPResponse * httpResponse = (NSHTTPResponse *) response;
if([httpResponse statusCode] == 401) { // WHAT TO DO HERE ?
dispatch_sync(dispatch_get_main_queue(), ^{
MyAppDelegate * delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate showLoginViewController callback:^(NSString * username, NSString * newToken) {
// recreate the NSURLSession and NSURLConfiguration with the new token and retry
MyRestfulModel.authenticationToken = token;
[self doSomeRestfulCall:callback];
}];
}
return;
} else {
callback(data);
}
}] resume];
}
我希望做这样使得视图控制器从来不需要担心重试呼叫由于令牌到期,所有可怕的会话处理和认证可以通过一个对象来完成。
我正在考虑尝试使用NSURLSessionDelegate,但我无法弄清楚didReceiveChallenge部分w.r.t.弹出登录视图控制器。我正在考虑的另一个选择是添加一个类似于完成处理程序的“retryHandler”,该程序将在用户重新验证后调用。