2015-01-02 6 views
1

У меня есть код, который работает - приложение MVC с использованием API календаря Google и API Gmail с аутентификацией OAuth2 от Google. Код работает. Когда страница загружается, отображаются данные из обеих служб. И у меня есть таймер Javascript для обновления данных с определенным интервалом (20 минут). Итак, все работает так, как ожидалось, пока в какой-то момент времени (после некоторого промежутка времени, я думаю) он начинает бросать исключение: Ошибка: «invalid_grant», Описание: «", Uri: "". Исключение не имеет InnerException и имеет только то, что сообщение об ошибке и эту информацию в StackTrace (здесь на скриншоте):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

Invalid Грант: Маркер ограничения обновления превышен (по умолчанию 25). Вот и все.

Согласно этой документации: В настоящее время на учетную запись пользователя Google в настоящее время действует ограничение на 25 токенов. Если учетная запись пользователя имеет 25 действительных токенов, следующий запрос на аутентификацию завершается успешно, но при этом недействителен недействительный старейший выдающийся токен без предупреждения пользователя.

Если приложение пытается использовать недействительный токен обновления, возвращается ответ об ошибке invalid_grant. Предел для каждой уникальной пары клиентов OAuth 2.0 и аккаунта Google Analytics составляет 25 токенов обновления (обратите внимание, что этот лимит может быть изменен).

Понял, что они ограничивают количество токенов обновления до 25, но они не говорят, что делать, когда вам нужно пройти выше этого предела. Arghhh ... Я экспериментировал и нашел решение, как обойти это ограничение. Кажется, что переработка Application Pool решает проблему (разумеется, до достижения 25-лимита). Мы можем вручную перерабатываем AppPool из IIS или выполнив команду:

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

Вы можете запланировать эту команду, чтобы выполнить каждую ночь или каждый час, независимо от ...

Но я нашел есть программное решение:

Override 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 исключения, исключение «проглотила»: журнал, AppPool перерабатывается и предел обновить токены. Надеюсь это поможет.

Пожалуйста, дайте мне знать, если вы найдете некоторые проблемы.

1

Также возможно, что часы сервера не синхронизированы. По какой-то причине мой не смог синхронизировать с интернет-часами и работал быстро на 6 минут. Сброс его до нужного времени.

+0

Это было именно это для меня. Я синхронизировал с NTP, а затем перезапустил IIS. http://nefaria.com/2013/03/configure-windows-server-20082012-to-sync-with-internet-time-servers/ – pharophy

Смежные вопросы