我正在尝试将我的应用转换到新的Facebook SDK 3.1(支持iOS6身份验证)。
我工作得很好,所以我决定从FB网站上的授权应用列表中删除该应用,以测试iOS会再次请求许可。
现在我第一次调用[FBRequest requestForMe]
会导致此错误:
响应:
{
"error": {
"message": "Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.",
"type":"OAuthException",
"code":190,
"error_subcode":460
}
}
一些细节:
我正在尝试按如下方式打开会话:
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
switch (state) {
case FBSessionStateOpen:
[self presentPostOptions];
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
然后我回到状态FBSessionStateOpen
(此时iOS还没有提出请求对话框,这是预期的)? Facebook记录了这个:
2012-09-26 13:43:43.768 MyApp[2177:907] FBSDKLog: FBSession INVALID transition from FBSessionStateCreated to FBSessionStateClosed
2012-09-26 13:43:43.769 MyApp[2177:907] FBSDKLog: FBSession transition from FBSessionStateCreated to FBSessionStateCreatedOpening
2012-09-26 13:43:43.837 MyApp[2177:907] FBSDKLog: FBSession transition from FBSessionStateCreatedOpening to FBSessionStateOpen
会话打开后,在presentPostOptions中执行此操作:
- (void)presentPostOptions
{
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
self.usersName = user.name;
self.usersID = user.id;
[self getPages];
}
else
{
[self didFailWithError:error];
}
}];
}
在回调上述完成块之前,我的主状态处理程序块以FBSessionStateClosed
状态调用。与此同时,Facebook SDK已记录上述错误。
我找不到任何重置系统的方法;我也不了解原因。
任何人都可以解释一下吗?
答案 0 :(得分:76)
设备上的Facebook帐户已与服务器以及App的/ SDK缓存不同步。这可以通过调用ACAccountStore方法renewCredentialsForAccount来解决,该方法将更新操作系统对令牌状态的理解。
在下次更新SDK时,SDK会在收到服务器的响应时自动调用此API,表明令牌已失效。对于SDK的3.1.0版本,应用程序将需要显式调用此API。这是一个代码示例:
ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) &&
(accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) ){
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
id account;
if (fbAccounts && [fbAccounts count] > 0 &&
(account = [fbAccounts objectAtIndex:0])){
[accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
//we don't actually need to inspect renewResult or error.
if (error){
}
}];
}
}
调用API的位置/时间有多种选择。最简单的地方是在应用程序启动或视图加载时机会性地调用。这种方法的一个问题是它将导致通常不必要的网络往返。另一种选择是在发生会话更改通知时调用它,指示会话已关闭。此外,许多应用程序在应用程序启动时获取一些基本信息,如graph.facebook.com/me,如果是这样的话 - 在出现错误响应时调用此方法可能是要求iOS更新其令牌的合理位置状态。
希望这有帮助!
答案 1 :(得分:7)
我只是要做出另一件事来检查,这让我浪费了3个小时: 如果您尝试使用非应用程序开发人员FB用户登录,请确保您的FB应用程序设置没有“沙盒”选项... 也许是显而易见的,但希望能在几个小时内拯救他人。
答案 2 :(得分:4)
如果您还没有,请按照建议settings panel在Facebook APP的here中添加您的iOS App Bundle ID。
希望这有帮助。
答案 3 :(得分:1)
我很确定这是一个Facebook iOS SDK错误(甚至在3.1.1上),我提交了this bug report。
在尝试使用他们的示例应用程序Scrumptious重现此错误时,我发现如果您使用openActiveSessionWithReadPermissions
,它可以让您成功重新授权。但是,如果您要求通过openActiveSessionWithPublishPermissions
发布权限,则会将其置于com.facebook.sdk.error 5
。
答案 4 :(得分:1)
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error)
{
switch (state) {
case FBSessionStateOpen:
[self presentPostOptions];
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
}];
答案 5 :(得分:0)
在facebook SDK 3.7.1中,我仍然有这个问题。基本上我决定在发生这种情况时从facebook缓存清除令牌。像这样:
if(state == FBSessionStateClosed ) {
[FBSession.activeSession closeAndClearTokenInformation];
}
答案 6 :(得分:0)
简单的Swift 2+解决方案,用于Facebook错误验证访问令牌
// Step 1: Logout
FBSDKLoginManager().logOut()
// Step 2: Login
FBSDKLoginManager().logInWithReadPermissions(["public_profile", "email"], fromViewController: self, handler: { result, error -> Void in
// ...
}
如果发生此错误,您必须创建新的 Facebook会话,因此您必须重新登录。