我不确定您是在尝试构建本地安装的应用程序还是 asp.net Web 应用程序,但根据您指出的问题,我假设它是一个 Web 应用程序,这就是我解决它的方法。
首先,GoogleWebAuthorizationBroker 的默认实现是针对本地安装的应用程序。你可以在这个link 中找到它的实现
.因此,您的代码可能在您的本地机器上运行良好,但当托管在网络服务器中时,它可能会永远加载。
因此,您需要为 google 文档中提到的 Web 应用程序实现自己的 AuthorizationCodeFlow。
这就是我在 ASP.NET Core MVC Web 应用程序中实现它的方式
public async Task<IActionResult> ConfigureGA(CancellationToken cancellationToken)
{
GoogleAnalyticsModel model = new GoogleAnalyticsModel();
var state = UriHelper.GetDisplayUrl(Request);
var result = await GetCredential(state, cancellationToken);
if (result.Credential != null)
{
using (var svc = new AnalyticsService(
new BaseClientService.Initializer
{
HttpClientInitializer = result.Credential,
ApplicationName = "Your App Name"
}))
{
ManagementResource.AccountSummariesResource.ListRequest list = svc.Management.AccountSummaries.List();
list.MaxResults = 1000;
AccountSummaries feed = await list.ExecuteAsync();
model.UserAccounts = feed.Items.ToList();
}
return View(model);
}
else
{
return new RedirectResult(result.RedirectUri);
}
}
private async Task<AuthorizationCodeWebApp.AuthResult> GetCredential(string state, CancellationToken cancellationToken)
{
var userId = userManager.GetUserAsync(User).Result.Id;
var redirectUri = Request.Scheme + "://" + Request.Host.ToUriComponent() + "/authcallback/";
using (var stream = new FileStream("client_secret.json",
FileMode.Open, FileAccess.Read))
{
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly, AnalyticsReportingService.Scope.AnalyticsReadonly },
DataStore = datastore
});
return await new AuthorizationCodeWebApp(flow, redirectUri, state)
.AuthorizeAsync(userId, cancellationToken);
}
}
我在请求 oauth 凭据(即 GetCredential() 方法)时传递了应用程序的状态。
在此方法中,创建您自己的 IAuthorizationCodeFlow 并将您的流程、redirect_uri(您还必须在 Google 开发者控制台中设置)和应用程序的状态传递给 AuthorizationCodeWebApp
接下来您必须实现 authcallback 控制器来处理 oauth 代码。此代码类似于 google-dotnet-client 库 found here,但我采用了相同的代码,因为我正在使用 Microsoft.AspNetCore.Mvc
public class AuthCallbackController : Controller
{
private readonly UserManager<ApplicationUser> userManager;
private readonly IGoogleAnalyticsDataStore datastore;
public AuthCallbackController(UserManager<ApplicationUser> userManager, IGoogleAnalyticsDataStore datastore)
{
this.userManager = userManager;
this.datastore = datastore;
}
protected virtual ActionResult OnTokenError(TokenErrorResponse errorResponse)
{
throw new TokenResponseException(errorResponse);
}
public async virtual Task<ActionResult> Index(AuthorizationCodeResponseUrl authorizationCode,
CancellationToken taskCancellationToken)
{
using (var stream = new FileStream("client_secret.json",
FileMode.Open, FileAccess.Read))
{
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
DataStore = datastore,
Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly, AnalyticsReportingService.Scope.AnalyticsReadonly }
});
if (string.IsNullOrEmpty(authorizationCode.Code))
{
var errorResponse = new TokenErrorResponse(authorizationCode);
return OnTokenError(errorResponse);
}
string userId = userManager.GetUserAsync(User).Result.Id;
var returnUrl = UriHelper.GetDisplayUrl(Request);
var token = await flow.ExchangeCodeForTokenAsync(userId, authorizationCode.Code, returnUrl.Substring(0, returnUrl.IndexOf("?")),
taskCancellationToken).ConfigureAwait(false);
// Extract the right state.
var oauthState = await AuthWebUtility.ExtracRedirectFromState(datastore, userId,
authorizationCode.State).ConfigureAwait(false);
return new RedirectResult(oauthState);
}
}
}
希望这能回答您的问题,并且超出了问题的范围。