【问题标题】:C# Error when using Google Sheets API with service account将 Google Sheets API 与服务帐户一起使用时出现 C# 错误
【发布时间】:2021-04-20 14:39:59
【问题描述】:

我正在尝试使用我的服务帐户在我的 .net 5 应用程序中使用 Google Sheets API。我从"quickstart" example 开始,它工作正常。但是我需要将我的应用程序放在 docker 容器中,因此使用浏览器的“快速启动”授权不适合我。 我决定尝试使用 google 服务帐户进行授权。我找到了this solution,但是当我尝试执行任何请求时,它会抛出错误'Error:"invalid_grant", Description:"Invalid JWT Signature.", Uri:""'

这是我的凭据设置代码:

using System.IO;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Sheets.v4;

namespace GoogleSheetsParser.Helpers
{
    public class GoogleSheetsServiceSettings
    {
        private static readonly string[] Scopes = { SheetsService.Scope.Spreadsheets };

        public static ServiceAccountCredential Credential { get; private set; }

        public static void Setup()
        {
            var serviceAccountEmail = "my@seviceaccount.iam.gserviceaccount.com";
            using Stream stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read, FileShare.Read);
            var credential = (ServiceAccountCredential)
                GoogleCredential.FromStream(stream).UnderlyingCredential;

            var initializer = new ServiceAccountCredential.Initializer(credential.Id)
            {
                User = serviceAccountEmail,
                Key = credential.Key,
                Scopes = Scopes
            };
            Credential = new ServiceAccountCredential(initializer);
        }
    }
}    

这是我的 Startup.cs

namespace GoogleSheetsParser
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddSingleton(Configuration);

            GoogleSheetsServiceSettings.Setup();
            var sheetsService = new SheetsService(new BaseClientService.Initializer
            {
                ApplicationName = Configuration.GetValue<string>("ApplicationName"),
                HttpClientInitializer = GoogleSheetsServiceSettings.Credential
            });
            
            services.AddSingleton(sheetsService);
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthentication();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

配置工作表服务的用法如下:

using Microsoft.AspNetCore.Mvc;
using Google.Apis.Sheets.v4;
using GoogleSheetsParser.Dto;

namespace GoogleSheetsParser.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class SheetsController : ControllerBase
    {
        private SheetsService SheetsService { get; }

        public SheetsController(SheetsService sheetsService)
        {
            SheetsService = sheetsService;
        }

        [HttpGet]
        public JsonResult GetSheets([FromQuery] GetSheetsRequestDto dto)
        { 
            var spreadsheet = SheetsService.Spreadsheets.Get(dto.SpreadsheetId).Execute();
        }
    }
}

在我的本地机器上的 Visual Studio 项目中测试它。

我错过了什么?

【问题讨论】:

  • 发布的代码是工作代码吗?
  • 它编译,如果你问这个:) 你为什么问?
  • 不清楚贴出的代码是工作代码还是非工作代码,工作代码和非工作代码有什么区别。
  • 好吧,当我以这种方式设置我的凭据时 - 任何请求都会失败并出现错误。我认为我不需要展示示例中的工作代码,因为它完全不同。
  • 我强烈建议。添加“使用”语句。并建议摆脱发布问题的“var”。缺少 using 语句和“var”重载的组合......读者很难知道这些对象是什么。

标签: c# google-sheets-api


【解决方案1】:

我有点不清楚为什么它在这里使用 JWT,但你绝对可以避免使用 GoogleCredential.CreateWithUserGoogleCredential.CreateScoped 那样低级。这是我在你的Setup 中写的代码:

using System.IO;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Sheets.v4;

namespace GoogleSheetsParser.Helpers
{
    public class GoogleSheetsServiceSettings
    {
        public static GoogleCredential Credential { get; private set; }

        public static void Setup() =>
            Credential = GoogleCredential.FromFile("credentials.json")
                .CreateScoped(SheetsService.Scope.Spreadsheets)
                .CreateWithUser("my@seviceaccount.iam.gserviceaccount.com");
    }
}

不清楚您为什么要将用户设置为不同的服务帐户 - 通常您使用CreateWithUser 来模拟具有服务帐户的普通用户。如果您想充当服务帐户,只需为该服务帐户生成一个带有凭据的 JSON 文件,而不必为模拟而烦恼。

【讨论】:

  • 对我来说很好用!
猜你喜欢
  • 2018-08-10
  • 2013-10-11
  • 2020-06-09
  • 2014-10-15
  • 2020-02-22
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多