2015-01-02 51 views
1

我有代码可以使用 - 使用Google Calendar API和Gmail API以及来自Google的OAuth2身份验证的MVC应用程序。代码起作用。加载页面后,将显示来自两种服务的数据。我有一个Javascript计时器刷新数据以一定的时间间隔(20分钟)。因此,一切都按预期工作,直到某个时间点(经过一段时间我猜)它开始抛出一个异常:错误:“invalid_grant”,描述:“”,Uri:“”。唯一的例外有没有的InnerException并具有唯一的错误消息和堆栈跟踪此信息(在这里的截图):TokenResponseException - 错误:“invalid_grant”,说明:“”,Uri:“”

enter image description here

我会很感激,如果有人有一个想法,这可能是该错误的原因。在堆栈跟踪消息中是什么“c:\ code \ google.com ....”行,我的磁盘上没有“c:\ code”文件夹。我发现有几个帖子涉及到相同的错误,但不幸的是他们没有帮助理解的问题。也许有更多的细节,像这个截图有人有关于这个问题的更多信息。非常感谢。

我发现了 - 是AppPool回收临时解决了这个问题。但是,过了一段时间后,它又回来了。它与AppPool回收有什么关系?

回答

1

好吧,经过更多的阅读,我发现了这个例外的原因。

https://developers.google.com/accounts/docs/OAuth2#expiration

https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization?#helpme

授权无效:刷新令牌数量已经超过(默认为25)。 就是这样。

根据以下文档:每个Google用户帐户目前存在25令牌限制。如果用户帐户有25个有效令牌,则下一个验证请求会成功,但会悄悄地使最旧的未完成令牌无效,而不会显示任何用户可见的警告。

如果应用程序尝试使用无效刷新标记,则返回invalid_grant错误响应。每个唯一一对OAuth 2.0客户端和Google Analytics帐户的限额为25个刷新标记(请注意,此限制可能会有所更改)。

了解的是,它们将刷新标记的数量限制为25个,但当您需要超出此限制时,他们不会说出要执行的操作。呃......我一直在试验,并找到了解决方法如何绕过这个限制。似乎的确回收应用程序池解决了问题(当然直到下一个25-限制达到)。我们可以手动从IIS或通过运行以下命令回收程序池:

c:\Windows\System32\inetsrv\appcmd.exe recycle apppool /apppool.name:AppPoolName 

您可以计划要执行的命令,每晚或每小时,无论...

但是我发现有一个纲领性的解决方案:

覆盖为控制器onException的方法(它是MVC应用程序)

protected override void OnException(ExceptionContext filterContext) 
{ 
    if (filterContext.ExceptionHandled) return; 

    // Log exception details 
    Global.LogException(filterContext.Exception, EventLogEntryType.Error); 

    if (filterContext.Exception.Message.Contains("invalid_grant")) 
    { 
     // Invalid Grant: The refresh token limit has been exceeded (default is 25). 
     // https://developers.google.com/accounts/docs/OAuth2#expiration 
     // https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization?#helpme 

     Global.RecycleAppPool(); 
     Global.LogException(new Exception("AppPool has been recycled"), EventLogEntryType.Information); 
     Response.Redirect("Index"); 
    } 

    var actionName = filterContext.RouteData.Values["action"].ToString(); 

    // Return friendly error message 
    var errorMessage = string.Format("Action {0} failed with error: {1}. Please try again.", actionName, filterContext.Exception.Message); 
    filterContext.Result = Content(errorMessage); 

    filterContext.ExceptionHandled = true; 
    base.OnException(filterContext); 
} 

凡RecycleAppPool是(这个操作是快速定义这个样子,不喜欢重新启动IIS :):

public static void RecycleAppPool() 
{ 
    ServerManager serverManager = new ServerManager(); 
    ApplicationPool appPool = serverManager.ApplicationPools["Homepage"]; 
    if (appPool != null) 
    { 
     if (appPool.State == ObjectState.Stopped) appPool.Start(); 
     else appPool.Recycle(); 
    } 
} 

所以,在invalid_grant异常的情况下,除了“吞噬”:登录,应用程序池被回收并为限刷新令牌被重置。希望这可以帮助。

请让你发现一些问题,我知道了。

1

这也有可能是服务器的时钟不同步。出于某种原因,我的是无法对互联网的时钟同步,并为运行6分钟快。将其重置为正确的工作时间。

+0

这正是对我来说。我与NTP同步,然后重新启动IIS。 http://nefaria.com/2013/03/configure-windows-server-20082012-to-sync-with-internet-time-servers/ – pharophy