由于这些答案都没有真正解决这个问题,我将详细说明我是如何使用 Facebook SDK 实现 OAuth 令牌刷新的。
SDK 会在您发出请求时自动刷新您的令牌,但是在我的场景中,我们将令牌发送到我们的服务器,并且我们需要使用最新的令牌。因此,当我们的服务器指示我们需要新令牌时,我们会这样做:
注意您可以将 AppID 传递给FBSession,也可以将FacebookAppID 键添加到您的应用程序列表中(这就是我们所做的)。
- (void)renewFacebookCredentials {
if (FBSession.activeSession.state == FBSessionStateOpen ||
FBSession.activeSession.state == FBSessionStateOpenTokenExtended) {
[self sessionStateChanged:[FBSession activeSession] state:[FBSession activeSession].state error:nil];
} else {
// Open a session showing the user the login UI
// You must ALWAYS ask for public_profile permissions when opening a session
[FBSession openActiveSessionWithReadPermissions:@[@"public_profile",@"email"]
allowLoginUI:NO
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
//this block will run throughout the lifetime of the app.
[self sessionStateChanged:session state:state error:error];
}];
}
}
您可以使用 Facebook 在其文档中包含的 sessionStateChanged: 方法,但简化的处理程序如下所示:
- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState) state error:(NSError *)error {
// If the session was opened successfully
NSString *accessToken;
if (!error && state == FBSessionStateOpen && [[session accessTokenData] accessToken]){
// Show the user the logged-in UI
//@see http://stackoverflow.com/questions/20623728/getting-username-and-profile-picture-from-facebook-ios-7
accessToken = [[session accessTokenData] accessToken];
//Now we have an access token, can send this to the server...
} else {
//No access token, show a dialog or something
}
//either call a delegate or a completion handler here with the accessToken
}
请注意,一些 FBSession API 调用会检查线程关联性,因此我发现我必须将所有 FBSession 调用包装在 dispatch_async(dispatch_get_main_queue(), ^{... 中