将 Google 工作表 API 与服务帐户一起使用时出现 C# 错误
C# Error when using Google Sheets API with service account
我正在尝试使用我的服务帐户在我的 .net 5 应用程序中使用 Google 表格 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 项目的本地机器上测试它。
我错过了什么?
我有点不清楚为什么它在这里使用 JWT,但你绝对可以避免使用 GoogleCredential.CreateWithUser
和 GoogleCredential.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 文件,其中包含该服务帐户的凭据,不要为模拟而烦恼。
我正在尝试使用我的服务帐户在我的 .net 5 应用程序中使用 Google 表格 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 项目的本地机器上测试它。
我错过了什么?
我有点不清楚为什么它在这里使用 JWT,但你绝对可以避免使用 GoogleCredential.CreateWithUser
和 GoogleCredential.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 文件,其中包含该服务帐户的凭据,不要为模拟而烦恼。