Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Google apps脚本执行API服务授权每小时失败一次_C#_Google Apps Script_Google Oauth_Google Apps Script Api - Fatal编程技术网

C# Google apps脚本执行API服务授权每小时失败一次

C# Google apps脚本执行API服务授权每小时失败一次,c#,google-apps-script,google-oauth,google-apps-script-api,C#,Google Apps Script,Google Oauth,Google Apps Script Api,我正在用我的C#应用程序执行谷歌应用程序脚本,大约每1.5分钟执行一次。应用程序脚本在电子表格之间移动内容,并编辑表格。我也使用驱动API 我的脚本在很长一段时间内运行良好,除了每小时有5分钟的授权错误 以下是我处理授权的代码: class Authentication { public static ScriptService ScriptsAuthenticateOauth(UserCredential credential) { try {

我正在用我的C#应用程序执行谷歌应用程序脚本,大约每1.5分钟执行一次。应用程序脚本在电子表格之间移动内容,并编辑表格。我也使用驱动API

我的脚本在很长一段时间内运行良好,除了每小时有5分钟的授权错误

以下是我处理授权的代码:

class Authentication
{

    public static ScriptService ScriptsAuthenticateOauth(UserCredential credential)
    {
        try
        {

            ScriptService service = new ScriptService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "MyApp",
            });

           return service;
        }
        catch (Exception ex)
        {
            Console.WriteLine(DateTime.Now.ToString("HH:mm") + ": An authentication error occurred: " + ex.InnerException);
            return null;
        }

    }


    public static UserCredential getCredential(string clientId, string clientSecret, string userName)
    {

        string[] scopes = new string[] { DriveService.Scope.Drive,  // view and manage your files and documents
                                         DriveService.Scope.DriveAppdata,  // view and manage its own configuration data
                                         DriveService.Scope.DriveAppsReadonly,   // view your drive apps
                                         DriveService.Scope.DriveFile,   // view and manage files created by this app
                                         DriveService.Scope.DriveMetadataReadonly,   // view metadata for files
                                         DriveService.Scope.DriveReadonly,   // view files and documents on your drive
                                         DriveService.Scope.DriveScripts, // modify your app scripts
                                         ScriptService.Scope.Drive,

                                         "https://www.googleapis.com/auth/spreadsheets",
                                         "https://spreadsheets.google.com/feeds",
                                         "https://docs.google.com/feeds"};  
        return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
                                                                                         , scopes
                                                                                         , userName
                                                                                         , CancellationToken.None
                                                                                         , new FileDataStore("Google.Sheet.Sync.Auth.Store")).Result;
    }

    public static DriveService DriveAuthenticateOauth(UserCredential credential)
    {
        try
        {


            DriveService service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "MyApp",
            });

            // Console.WriteLine("Auth success");


            return service;
        }
        catch (Exception ex)
        {

            // Console.WriteLine(ex.InnerException);
            Console.WriteLine(DateTime.Now.ToString("HH:mm") + ": An authentication error occurred: " + ex.InnerException);
            return null;

        }

    }
}
我得到的服务如下:

 var credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
 DriveService driveService = Authentication.DriveAuthenticateOauth(credential);
 ScriptService scriptService = Authentication.ScriptsAuthenticateOauth(credential);
但大约在一小时结束时,apps脚本调用抛出以下错误:

Script error message: Authorization is required to perform that action.
说清楚一点,它在所有其他时间都有效,只是在接近一小时结束的那5分钟内不起作用。我在开发者控制台和参考资料>高级谷歌服务下都激活了谷歌驱动API。。。在应用程序脚本编辑器中


那么到底发生了什么?这可以解决吗?

在做进一步的研究后,我发现脚本只需要从脚本编辑器中运行就可以防止此错误。这是我找到的信息:

执行该操作需要授权。

此错误表示脚本缺少运行所需的授权。在脚本编辑器中或从自定义菜单项运行脚本时,将向用户显示授权对话框。但是,当脚本作为服务运行、嵌入Google站点页面或从触发器运行时,将无法显示对话框,并显示此错误。要授权脚本,请打开脚本编辑器并运行任何函数。要避免此错误,请记住在向脚本添加新服务或功能后在脚本编辑器中运行脚本一次

资料来源:

我对代码所做的另一个相关改进是在创建两个服务之前获取credentials对象的新副本:换句话说,我更改了以下内容:

var credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
DriveService driveService = Authentication.DriveAuthenticateOauth(credential);
ScriptService scriptService = Authentication.ScriptsAuthenticateOauth(credential);
为此:

var credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
DriveService driveService = Authentication.DriveAuthenticateOauth(credential);
credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
ScriptService scriptService = Authentication.ScriptsAuthenticateOauth(credential);

这本身并没有解决我的问题,但它有助于避免OAuth的怪癖,并可以防止不必要的令牌刷新。

您可能需要一个刷新令牌。谷歌通常将访问令牌的有效期设置为3600秒(1小时),而刷新令牌的有效期要长得多,其设计可以让您在前一个访问令牌过期时轻松获得新的访问令牌。这可能是一个很好的起点:

此外,如果您没有刷新令牌,但您确实有访问令牌,则可以撤销以前的访问令牌,然后再次进行身份验证。如果正确调用“确保您获得的是
“承载者”
令牌类型),则新响应将具有刷新令牌

有关使用寿命更长的刷新令牌的更多信息。

如果您的应用程序“在接近一小时结束的那5分钟内”失败,您很可能会遇到

显然,对带有将在6分钟内过期的令牌的执行API的请求会出现“需要授权…”错误。这似乎与6分钟是脚本的最大运行时间这一事实有关

一个解决方法是提前刷新你的令牌,如果你知道它什么时候会过期(Android上不是这样),希望这个错误很快会被修复


我不确定您是否真的解决了问题,或者您是否找到了一个好的解决方法,但您可能希望启动应用程序脚本问题,以便能够更快地解决问题。

似乎您正在传递过期的访问令牌。如果是,请阅读oauth2以及如何处理刷新和访问令牌。