繁体   English   中英

如何在处理使用Facebook API调用的服务方法时透明地更新Facebook访问令牌?

[英]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信息(如此处所示 )。

我有两个问题:

  • 调用我的服务方法并从数据库中检索相应用户的令牌时,是否有办法知道访问令牌是否已过期?
    我已经读过 ,当执行Facebook API调用并且访问令牌过期时,会抛出以下异常: OAuthException 但有没有更好的方法来检测到期? 我不想
    1. 调用Facebook API
    2. 处理异常
    3. 最后更新访问令牌
    4. 使用新的访问令牌重复初始调用。
  • 是否可以透明地更新用户的访问令牌(也将其存储在数据库中)并继续处理服务方法? 资源中,缺少重要的(“更新访问令牌”)部分(声明为[todo])

我想在服务方法的实现中实现以下方案:

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的通信以获取访问令牌,这是同步执行的。

最后的问题:

  • 有没有办法让服务方法等待我们从Facebook请求/回调中检索的新访问令牌,以便稍后继续使用新的访问令牌?

我不知道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令牌并不是您可以等待响应的请求,它实际上会触发最终导致单独获取请求的内容
Facebook API请求 请注意,尽管上图是针对用户首次登录时的情况,但大致在失败的呼叫中会发生相同的序列,但它会从重定向开始。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM