我有一个令牌但仍然收到此错误:“必须使用活动访问令牌来查询有关当前用户的信息。”任何帮助表示赞赏:)
NSLog(@"TOKEN : %@",[[FBSession activeSession] accessToken]);
NSString *picture = [NSString stringWithFormat:@"http://www.prowebdev.org/WooF/API/OpenGraph.php"];
NSString *image = [NSString stringWithFormat:@"http://www.prowebdev.org/WooF/API/upload/356.jpg"];
NSString *imageBool = [NSString stringWithFormat:@"true"];
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:picture,image,imageBool, nil] forKeys:[NSArray arrayWithObjects:@"picture",@"image[0][url]",@"image[1][user_generated]", nil]];
FBRequest *request = [FBRequest requestWithGraphPath:@"me/mydogwoofs:posted" parameters:myDictionary HTTPMethod:@"POST"];
FBRequestConnection *connection = [[FBRequestConnection alloc] init];
[connection addRequest:request completionHandler:
^(FBRequestConnection *connection, id result, NSError *error) {
if (!error && result) {
NSLog(@"Posted!");
}else{
NSLog(@"ERROR - %@", error);
}
}];
[connection start];
LOG:
TOKEN : CAAD2QmzDZCHUBALgvURs9AmdO0ZCyj4Uws1pHbX9FYMbptaZAehn6318DEQPyiWpCDWs5O4DXoyAHiBajy37HAdkO648mOgpOZCxc73JhR9n0eO3KejeEkmgKTNSJti2GRmGuZCfhVm9X4cQhhk35ksfEdN8AGR7R6aP3dZBGFWQZDZD
Error: HTTP status code: 400
ERROR - Error Domain=com.facebook.sdk Code=5 "The operation couldn’t be completed. (com.facebook.sdk error 5.)" UserInfo=0x8b8abd0 {com.facebook.sdk:ParsedJSONResponseKey=<CFBasicHash 0x8b88fe0 [0x1bc3b48]>{type = mutable dict, count = 2,
entries =>
1 : <CFString 0x952a8 [0x1bc3b48]>{contents = "code"} = <CFNumber 0x8b885d0 [0x1bc3b48]>{value = +400, type = kCFNumberSInt32Type}
2 : <CFString 0x93eb8 [0x1bc3b48]>{contents = "body"} = <CFBasicHash 0x8b75ae0 [0x1bc3b48]>{type = mutable dict, count = 1,
entries =>
11 : <CFString 0x8b88f20 [0x1bc3b48]>{contents = "error"} = <CFBasicHash 0x8b888d0 [0x1bc3b48]>{type = mutable dict, count = 3,
entries =>
2 : <CFString 0x8b5f550 [0x1bc3b48]>{contents = "type"} = <CFString 0x8b88aa0 [0x1bc3b48]>{contents = "OAuthException"}
3 : <CFString 0x8b88a40 [0x1bc3b48]>{contents = "message"} = <CFString 0x8b889a0 [0x1bc3b48]>{contents = "An active access token must be used to query information about the current user."}
6 : <CFString 0x8b88e40 [0x1bc3b48]>{contents = "code"} = 2500
答案 0 :(得分:8)
好的,对我有用的是使用来自friendpicker示例应用程序的解决方案。
需要检查会话是否已打开,如果不是,则打开会话。
if (!FBSession.activeSession.isOpen) {
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
} else if (session.isOpen) {
//run your user info request here
}
}];
答案 1 :(得分:3)
我不确定这是否会导致您的问题,但我过去曾经遇到过Facebook SDK积极缓存的问题。由于Facebook SDK在多个位置查找有效登录的Facebook用户,因此通过缓存当前登录的用户,可以在后续调用中将此搜索短路。如果任何一个可能登录的Facebook用户更改,或者该用户的auth更改,那么事情可能会有点疯狂。
为了给你一个想法,Facebook SDK尝试iOS 5+系统的Facebook帐户,应用程序间的应用程序调用facebook自己的原生应用程序,运行在您的应用程序中的Web视图实例的浏览器cookie,或者反弹到safari并在safari中使用浏览器cookie ...因此,如果其中任何一个不同的登录帐户发生更改,或者其中一个帐户被修改了权限或更改了其密码(例如),如果SDK过于激进地缓存,事情就会变得混乱。为了解决这个问题,在打开Facebook SDK会话后,我总是针对图形api检查访问令牌。如果它通过简单的“我”测试,那么我将接受此访问令牌作为有效并继续。但是,如果失败,那么我刷新SDK中的缓存值并强制Facebook SDK重新打开一个全新的会话,这会返回所有可能登录的Facebook帐户以查找活动会话。这可能会也可能不会导致新的应用程序身份验证提示...但是它应该为您的应用程序生成一个工作访问令牌。
为了帮助您了解我正在做的事情,这里有一些半伪代码。 (不幸的是,我已抽出太多东西,以便能够轻松地复制粘贴一组有用的代码,所以你必须在几个地方填写空白:P)
主要循环
我的Facebook代码的入口点以if语句开头,该语句查看Facebook SDK activeSession的当前状态,并重新提供或验证访问权限:
if (isSet(FBSession.activeSession) &&
(FBSession.activeSession.isOpen || FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded))
{
// Make sure the access_token is still authed and has the correct permissions first (can't trust what's cached by fb's sdk)
[self checkAgainstGraphAPIOnVerified:^
{
// From the api the access_token looks ready, make sure fb sdk session is open as well
if (FBSession.activeSession.isOpen)
{
// We're authenticated and session is open, good to go
[self runIfFullAuth];
}
else if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded)
{
// We have a cached token (permissions all look good), we need to re-open the fb sdk session
[FBSession.activeSession openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent
completionHandler:openSessionHandler];
}
}
onInvalidated:^
{
// App isn't removed, but don't have required permissions anymore...
if (FBSession.activeSession.isOpen)
{
// We have an open fb session, so just reprompt for permissions
[self repromptForPermissions];
}
else if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded)
{
// We have a cached token, we need re-open the session first before reprompting
[FBSession.activeSession openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent
completionHandler:openSessionHandler];
}
}
onAppRemoved:^
{
// App is completely removed, so prompt for permissions
[self openNewFBSession];
}];
}
else
{
// No valid access_token cached, prompt for permissions
[self openNewFBSession];
}
调用的大多数函数应该非常简单。例如,runIfFullAuth
只是在用户完全验证后调用您想要的任何内容,并且您拥有经过验证的访问令牌。 checkAgainstGraphAPIOnVerified:onInvalidated:onAppRemoved:
是我自己的函数,使用访问令牌graph.facebook.com/me?fields=permissions
对FBSession.activeSession.accessTokenData.accessToken
进行简单的调用。如果我在返回的json中返回一个id,那么我有一个经过验证的访问令牌。如果我在json返回时缺少任何必需的权限,那么我有一个无效的访问令牌。如果我从图表api中得不到任何回复,那么我会认为该应用程序正在删除。
<强> openSessionHandler 强>
openSessionHandler
负责了解我们请求开放会话后Facebook SDK返回给我们的内容。以下是它正在做的事情:
void(^openSessionHandler)(FBSession *, FBSessionState, NSError *) = ^(FBSession *session, FBSessionState status, NSError *error) {
{
if (error)
{
// Analyze the error
if (error.fberrorShouldNotifyUser)
{
// Pop up alert for error
if ([error.userInfo[FBErrorLoginFailedReason] isEqualToString:FBErrorLoginFailedReasonSystemDisallowedWithoutErrorValue])
{
// App disabled in facebook settings... pop up alert
}
else if ...
else if ...
else if ...
else
{
// Show pop up alert with error.fberrorUserMessage
}
[self runIfNoAuth];
}
else if (error.fberrorCategory == FBErrorCategoryUserCancelled)
{
// User canceled
[self runIfNoAuth];
}
else if (error.fberrorCategory == FBErrorCategoryAuthenticationReopenSession)
{
[self repromptForPermissions];
}
else
{
// Something else happened... probably network issue with Facebook servers
[self runIfNoAuth];
}
}
else
{
switch (status)
{
case FBSessionStateOpen:
{
[self checkAgainstGraphAPIOnVerified:^
{
[self runIfFullAuth];
}
onInvalidated:^
{
[self repromptForPermissions];
}
onAppRemoved:^
{
// If we're here, then we're in a fucked up state. We just prompted the user for auth, and
// the facebook sdk thinks we have an open session, but an api call proves that we're not actually
// authed. A few possible ways to get to this point:
// 1) The multi-screen auth inside facebook's ios app is used (ie. not system facebook account) and
// the user grants general permissions, but before granting posting permission (second page),
// goes to facebook.com and removes application permissions
// 2) The user's facebook account password has changed, and the phone's system facebook account
// hasn't been updated with the new password
// Pop up alert... tell user to check their Facebook settings
[self runIfNoAuth];
}];
break;
}
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
{
[self clearCachedFBInfo];
// If you want, you can choose to reprompt the user for permissions here... but it would most likely result in an endless loop where the only way out is for the user to log in :)
[self runIfNoAuth];
break;
}
default:
break;
}
}
};
<强> clearCachedFBInfo 强>
最后,这是你如何清除Facebook SDK的缓存会话信息:
[FBSession.activeSession closeAndClearTokenInformation];
[FBSession.activeSession close];
[FBSession setActiveSession:nil];
说实话,我不知道对close
的第二次电话是否多余......但这就是我一直这样做的方式......哈哈哈
哦,在我的函数openNewFBSession
的顶部,当我需要强制Facebook SDK重新开始并搜索新的Facebook会话时,我调用它,我调用我的clearCachedFBInfo
函数。这保证我在SDK中没有缓存的Facebook信息,然后我去打开一个新的会话。
最后,我仍然不知道这是否会导致您所看到的问题,但我肯定遇到了非常令人讨厌的问题,看似有效的访问令牌过去无效,这是我如何解决我的问题。祝好运!我很乐意回答您的任何问题!