Google MVC 身份验证问题:'AppFlowMetaData' 的类型初始值设定项抛出异常。但是代码在本地工作
Google MVC Auth Issue: The type initializer for 'AppFlowMetaData' threw an exception. But the code works locally
首先:我看到其他几个线程在谈论类似的问题,但是这些线程的答案只是指向我在代码中用作参考的页面,所以请不要杀死这只是因为它看起来很相似。
我只在生产 IIS 实例上收到错误 "The type initializer for 'Models.AppFlowMetaData' threw an exception."
BUT。这在本地工作正常,我已经三次检查了 return url (无论如何这给出了不同的错误) 我唯一能想到的是 Auth 被某种方式阻止了. Google 开发控制台没有显示任何错误。
错误发生在以下代码中:
private static string[] scopes = { SheetsService.Scope.Spreadsheets, DriveService.Scope.Drive };
private static readonly IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer {
ClientSecrets = new ClientSecrets {
ClientId = "[App id].apps.googleusercontent.com",
ClientSecret = "[secret]" },
Scopes = scopes,
DataStore = new FileDataStore("Drive.Api.Auth.Store") });
public override IAuthorizationCodeFlow Flow { get { return flow; } }
以上代码基于 google 网站上给出的身份验证示例:Google API Auth for MVC
以上代码调用自:
private async Task<UserCredential> GetGoogleCreds()
{
Google.Apis.Auth.OAuth2.Web.AuthorizationCodeWebApp.AuthResult result;
try
{
var log = LogManager.GetCurrentClassLogger();
log.Info("GetGoogleCreds: getting temp appflowmetadata");
var temp = new Models.AppFlowMetaData();
result = await new AuthorizationCodeMvcApp(this, new Models.AppFlowMetaData()).AuthorizeAsync(new CancellationTokenSource().Token);
if (result.Credential == null)
{
LoggingIntoGoogle = null;
throw new ApiException(500, result.RedirectUri);
}
return result.Credential;
}
catch(ApiException ex)
{
throw ex;
}
catch(Exception ex)
{
ERROR(ref ex);
throw ex;
}
return null;
}
上面抛出的 APIException 告诉调用进程 Google 还没有登录,所以它重定向到 Google OAuth 结果(当它可以到达那么远时)。
好的,这里的问题是 FileDataStore 和缺少 Google 实际记录的东西。
如果流中的文件数据存储保留为 Web 示例中的原样,它将在适当的 IIS 服务器上失败。
它尝试在 windows 受限文件夹下创建文件夹 (该示例表明它使用 google 驱动器,但实际上没有)(程序数据等),这当然会在 low-security 服务器设置上导致各种错误。
您必须使用 Server.MapPath()
并映射到可以写入的本地网站文件夹,例如 app_data。
对于上面的示例,我通过使用额外的组合让 google 使用 App_Data 下的文件夹来使其工作:
private static readonly IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer {
ClientSecrets = new ClientSecrets {
ClientId = "[client id].apps.googleusercontent.com",
ClientSecret = "[secret]" },
Scopes = scopes,
DataStore = new FileDataStore(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data/"), "FileDataStore")) });
首先:我看到其他几个线程在谈论类似的问题,但是这些线程的答案只是指向我在代码中用作参考的页面,所以请不要杀死这只是因为它看起来很相似。
我只在生产 IIS 实例上收到错误 "The type initializer for 'Models.AppFlowMetaData' threw an exception."
BUT。这在本地工作正常,我已经三次检查了 return url (无论如何这给出了不同的错误) 我唯一能想到的是 Auth 被某种方式阻止了. Google 开发控制台没有显示任何错误。
错误发生在以下代码中:
private static string[] scopes = { SheetsService.Scope.Spreadsheets, DriveService.Scope.Drive };
private static readonly IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer {
ClientSecrets = new ClientSecrets {
ClientId = "[App id].apps.googleusercontent.com",
ClientSecret = "[secret]" },
Scopes = scopes,
DataStore = new FileDataStore("Drive.Api.Auth.Store") });
public override IAuthorizationCodeFlow Flow { get { return flow; } }
以上代码基于 google 网站上给出的身份验证示例:Google API Auth for MVC
以上代码调用自:
private async Task<UserCredential> GetGoogleCreds()
{
Google.Apis.Auth.OAuth2.Web.AuthorizationCodeWebApp.AuthResult result;
try
{
var log = LogManager.GetCurrentClassLogger();
log.Info("GetGoogleCreds: getting temp appflowmetadata");
var temp = new Models.AppFlowMetaData();
result = await new AuthorizationCodeMvcApp(this, new Models.AppFlowMetaData()).AuthorizeAsync(new CancellationTokenSource().Token);
if (result.Credential == null)
{
LoggingIntoGoogle = null;
throw new ApiException(500, result.RedirectUri);
}
return result.Credential;
}
catch(ApiException ex)
{
throw ex;
}
catch(Exception ex)
{
ERROR(ref ex);
throw ex;
}
return null;
}
上面抛出的 APIException 告诉调用进程 Google 还没有登录,所以它重定向到 Google OAuth 结果(当它可以到达那么远时)。
好的,这里的问题是 FileDataStore 和缺少 Google 实际记录的东西。
如果流中的文件数据存储保留为 Web 示例中的原样,它将在适当的 IIS 服务器上失败。
它尝试在 windows 受限文件夹下创建文件夹 (该示例表明它使用 google 驱动器,但实际上没有)(程序数据等),这当然会在 low-security 服务器设置上导致各种错误。
您必须使用 Server.MapPath()
并映射到可以写入的本地网站文件夹,例如 app_data。
对于上面的示例,我通过使用额外的组合让 google 使用 App_Data 下的文件夹来使其工作:
private static readonly IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer {
ClientSecrets = new ClientSecrets {
ClientId = "[client id].apps.googleusercontent.com",
ClientSecret = "[secret]" },
Scopes = scopes,
DataStore = new FileDataStore(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data/"), "FileDataStore")) });