我正在使用 Google 的 GTMOAuth for iOS/Mac SDK,以便能够连接 YouTube API 和 Instagram API 等 API。一切正常,但是当用户进行身份验证时,我只能获取访问令牌。这一切都很好,但是一段时间后访问令牌过期并且用户必须重新登录,这很糟糕。
我的问题是,当用户进行身份验证时,我只得到一个访问令牌,没有别的......
谢谢你的帮助:)
我正在使用 Google 的 GTMOAuth for iOS/Mac SDK,以便能够连接 YouTube API 和 Instagram API 等 API。一切正常,但是当用户进行身份验证时,我只能获取访问令牌。这一切都很好,但是一段时间后访问令牌过期并且用户必须重新登录,这很糟糕。
我的问题是,当用户进行身份验证时,我只得到一个访问令牌,没有别的......
谢谢你的帮助:)
可能是这个帮助你..!
我正在使用 Google oauth 2.0 进行 Google 驱动器身份验证。
在 Google 完成身份验证方法中,像这样在 NSUSerDefaults 中保存 accesstoken 和刷新令牌值。
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)authResult
error:(NSError *)error
{
if (error != nil)
{
[self showAlert:@"Authentication Error" message:error.localizedDescription];
self.driveService.authorizer = nil;
}
else
{
self.driveService.authorizer = authResult;
self.auth = authResult;
NSLog(@"\n accessToken value is %@",self.auth.accessToken);
[[NSUserDefaults standardUserDefaults] setValue:self.auth.refreshToken forKey:@"refreshToken"];
[[NSUserDefaults standardUserDefaults] setValue:self.auth.accessToken forKey:@"accessToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
之后,当您想使用访问令牌执行 api 调用时,首先使用 NSUSERDefaults 中的现有 accesstoken 值进行调用,然后在 url 响应中检查状态代码。如果您收到状态代码“401”,则表示您的访问令牌已过期且无效。然后你必须像这样在 NSUserDefaults 中使用保存的刷新令牌值来请求刷新令牌。
这是您第一次检查 accesstoken 是否有效的 api 调用。
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"Did Receive Response %@", response);
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
//int responseStatusCode = [httpResponse statusCode];
if (httpResponse.statusCode == 200) {
//Your api call success and accesstoken is valid.
} else if(httpResponse.statusCode == 401 && connection == self.conn2) {
[[self appDelegate] refreshAccessToken];
}
}
这是从刷新令牌请求新的访问令牌。
-(void)refreshAccessToken {
NSString *requestString = [NSString stringWithFormat:@"https://accounts.google.com/o/oauth2/token"];
NSString *string = [NSString stringWithFormat:@"client_id=%@&client_secret=%@&refresh_token=%@&grant_type=refresh_token",kClientID,kClientSecret,[[NSUserDefaults standardUserDefaults] valueForKey:@"refreshToken"]];
NSData *postData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestString]];
NSLog(@"\n request str : %@",request);
NSLog(@"\n refresh token value is %@",[[NSUserDefaults standardUserDefaults] valueForKey:@"refreshToken"]);
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];//connectionWithRequest:request delegate:self];
if(connection)
{
NSLog(@"Connection Successful");
}
else
{
NSLog(@"Connection could not be made");
}
[connection start];
}
作为响应,再次检查状态代码,如果状态代码为 200。然后更新 userdafaults 中的值。
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"Did Receive Response %@", response);
//NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
self.data = [NSMutableData data];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
NSLog(@"Did Receive Data %@", data);
[self.data appendData:data];
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
NSLog(@"Did Fail %@",error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Did Finish");
// Do something with responseData
NSError *err;
id JSon = [NSJSONSerialization JSONObjectWithData:self.data options:kNilOptions error:&err];
if (err) {
NSLog(@"%@",err);
}
else {
NSLog(@"Json %@",JSon);
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"accessToken"];
[[NSUserDefaults standardUserDefaults] setObject:[JSon valueForKey:@"access_token"] forKey:@"accessToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
这是我关于堆栈溢出的第一个答案。抱歉有任何错误。
以下更新 - 由 Supertecnoboff 撰写
也请记住这一点。对于某些 API,例如 Google,如果您希望它为您提供刷新令牌,则需要添加“approval_prompt=force”和“access_type=offline”。为了添加这些参数,您必须编辑 GTMOAuth2SignIn.m 文件并将“paramsDict”替换为此 NSMutableDictionary:
NSMutableDictionary *paramsDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"code", @"response_type",
clientID, @"client_id",
scope, @"scope", // scope may be nil
@"force", @"approval_prompt",
@"offline", @"access_type",
nil];
您还可以使用GTMOAuth2Authentication的authorizeRequest:completionHandler:
方法
如果您的应用程序将授权保存到钥匙串(通过设置控制器的 keychainItemName),则可以在下次应用程序启动时检索它:
GTMOAuth2Authentication *auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientID
clientSecret:kClientSecret];
NSLog(@"accessToken: %@", auth.accessToken); //If the token is expired, this will be nil
然后您可以像这样刷新访问令牌:
// authorizeRequest will refresh the token, even though the NSURLRequest passed is nil
[auth authorizeRequest:nil
completionHandler:^(NSError *error) {
if (error) {
NSLog(@"error: %@", error);
}
else {
NSLog(@"accessToken: %@", auth.accessToken); //it shouldn´t be nil
}
}];
然后令牌将被刷新,您可以继续进行查询。