[英]How to transparently renew the Facebook access token while processing a service method which uses Facebook API calls?
我有一个在IIS 7.5和VS 2010中运行的WCF服务。此服务有一些方法在内部使用Facebook C#SDK (版本4.1,而不是最新版本),以便从/向Facebook执行一些GET和POST。 由于Facebook将很快删除 offline_access
我必须处理访问令牌过期的情况。
我已经了解了执行身份验证的方式(为了获取代码并在获取访问令牌之后),以便使用Graph API获取Facebook信息(如此处所示 )。
我有两个问题:
OAuthException
。 但有没有更好的方法来检测到期? 我不想 我想在服务方法的实现中实现以下方案:
sc = SocialNetworkAccountDao.GetByUser(user)
isExpired = call method to check if the sc.token is expired.
if (isExpired)
{
newToken = call method for getting new access token
sc.token = newToken;
SocialNetworkAccount.Update(sc);
}
Facebook = new Facebook (sc.token)
Facebook.Post( ..... )
--
与QAuth
对话通信的过程是异步的(执行重定向),并且与访问令牌url的通信以获取访问令牌,这是同步执行的。
最后的问题:
我不知道C#SDK,但所有facebook SDK基本上只是http请求图表不同网址的包装。
如果您使用服务器端身份验证流程,那么您应该获得一个长期存在的令牌(大约60天),并且您获得它的到期时间,当它到期时您需要重新验证用户,没有办法扩展令牌。
客户端身份验证返回一个短期令牌(大约2小时),但您可以使用提供的新端点 facebook来替换“offline_token”。 您只能将其用于仍然有效的访问令牌。
此外,无论如何,当您获得访问令牌时,您始终会获得“到期”时间,除非它是没有到期日期的应用程序令牌。
在任何一种情况下,如果您获得一个长期存在的令牌,您可以将其存储在数据库中并在服务器端使用它,但请注意,由于多种原因令牌仍然无效。
您还可以使用处理无效和过期访问令牌的官方文档。 如果C#SDK不适合您,那么您可能希望自己实现它,为了您自己的需要,应该非常简单。
您应该将c#sdk更新到最新版本 - 它们会随着时间的推移解决很多问题。
续订令牌
这是我们处理续订调用的代码(c#sdk ver 6.0.16,但这也适用于早期版本):
/// <summary>
/// Renews the token.. (offline deprecation)
/// </summary>
/// <param name="existingToken">The token to renew</param>
/// <returns>A new token (or the same as existing)</returns>
public static string RenewToken(string existingToken)
{
var fb = new FacebookClient();
dynamic result = fb.Get("oauth/access_token",
new {
client_id = FACEBOOK_APP_ID,
client_secret = FACEBOOK_APP_SECRET,
grant_type = "fb_exchange_token",
fb_exchange_token = existingToken
});
return result.access_token;
}
Facebook表示新令牌可能是相同的(但延长到期时间)或全新的令牌,因此如果需要,您应该在逻辑中处理它。
根据Facebook的说法,你应该每天更新一次。 ( https://developers.facebook.com/roadmap/offline-access-removal/ )
我们在上次“Facebook更新”完成时保留时间戳,如果该时间超过24小时并且用户正在访问我们的应用程序,我们将在后台进行更新令牌。
(我们还会更新其他数据,姓名,电子邮件和其他我们需要的东西)
显然,它不会每天调用一次,而是每个令牌调用一次。
Facebook不会让你续订一个长期存在的令牌。 请参阅脱机访问删除页面上的 “方案4:”
澄清一下:短命代币来自客户,长寿代币来自服务器端。
简而言之,当用户访问您的应用程序时,使用客户端的SDK获取一个新的短期令牌将其发送到服务器,并使用您的服务器扩展它以使其成为一个长期存储并存储,因此您获得从那时起60天。
处理过期时间
在我们当前的用法中,我们不需要保持到期时间的跟踪,因为所有访问都是从检查它的客户端开始的,但在相同的代码访问结果中result.access_token
它可以访问result.expires
,它返回秒数留在新获得的令牌上(应该接近5密尔=> 60天))。
在任何情况下,我都不确定是否有办法从令牌获取到期时间而不再调用auth进程。 我知道Facebook调试器会返回这个,但这并没有真正帮助..
续订无效令牌
这将无效 ,您将在尝试续订过期/无效令牌时获得此处所述的任何错误。
请记住在续订到期之前调用续订并记住,当您在过期(或任何其他类型的无效)上调用续订时,您将收到错误并需要处理它(我们在我粘贴的代码之外处理它)。
简短的回答:你得到秒数,直到它过期,但c#api似乎不暴露它。
根据这个 facebook文档,当你获得令牌时,你得到令牌到期时的秒数。 文档将响应格式列为:
access_token=USER_ACESS_TOKEN&expires=NUMBER_OF_SECONDS_UNTIL_TOKEN_EXPIRES
这得到了Ouath 2的RFC草案的支持,该草案称响应应该包含到期时间。
不幸的是,它与此处所述的C#SDK文档直接相矛盾
如果没有向Facebook发出请求,则无法确定访问令牌是否过期。 因此,您必须始终假设在向Facebook发出请求时,访问令牌可能已过期。
这不是真的。 如果查看c#SDK源代码,sdk为OAuth响应创建的对象显式包含(不幸的是作为私有变量)以下代码
/// <summary>
/// Date and Time when the access token expires.
/// </summary>
private readonly DateTime _expires;
所以它有数据,但由于某种原因不暴露它(至少在那里,我没有进一步看)。 我要说要么更多地挖掘库,看看它是否暴露在某个地方,在github上分叉和修补它(我相信这是一行更改),或者使用反射来读取你自己代码中的私有变量。
简短的回答:也许吧。 如果您知道令牌已过期,您可以在请求之前明显地获得新令牌。
如果你没有,那么你可以,但你需要处理你的请求失败。 从理论上讲,这并不意味着您需要处理异常,只需查看http状态代码(400个中的一个可能是403禁止)但是C#的webrequest方法将非200状态c作为引发异常的事件进行处理。 由于API使用此机制进行调用,因此只有在失败时才会出现异常。
当然,在你处理异常之后。
一旦发生这种情况,异步,您将获得一个新的身份验证令牌。 因此,您可以在捕获异常后等待一段时间,检查是否为该用户获取了新令牌,如果是,则重试。 如果继续等待和检查。 确保您有最大重试次数和最长等待时间。 拉动数据库以检查更改是有点低效的,因此您可能希望选择仔细检查更改的时间间隔,并可能使其以指数方式退回 。
另一个更有效的(对于单个服务器),但是复杂的方式是让系统通过auth令牌获取回调引发事件并让重试逻辑监听这些事件。
当您的代码因令牌过期而获得异常时,在catch块中创建一个函数,该函数将重做请求,然后将其作为事件侦听器添加到auth事件中。 让函数检查事件是否为请求事件的用户提供了新的身份验证令牌,如果是,请发出请求。 再次,记住要有最大重试次数。
实际上不可能使用async / await或类似的东西等待您的新令牌的请求完成。 问题是,刷新API令牌并不是您可以等待响应的请求,它实际上会触发最终导致单独获取请求的内容 请注意,尽管上图是针对用户首次登录时的情况,但大致在失败的呼叫中会发生相同的序列,但它会从重定向开始。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.