在本地测试时,我能够进行身份验证。使用Oauth2Service
检索帐户创建的基本信息。一旦它上线,用户就能够访问谷歌同意页面,但一旦他们选择了一个帐户(或输入了他们的谷歌凭证),它就会坐在加载屏幕上,直到达到我预定义的超时60秒。
我目前收到以下错误:
操作已经超时。
描述:执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。
异常详细信息:System.TimeoutException:操作已超时。
来源错误:
在执行当前Web请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪来识别有关异常的起源和位置的信息。
堆栈追踪:
[TimeoutException:操作已超时。] System.Web.Mvc.Async。<> c__DisplayClass8.b__4()+189 System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult)+427 System.Web.Mvc.Async。<> c__DisplayClass37.b__36(IAsyncResult asyncResult)+23 System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d()+112 System.Web.Mvc.Async。<> c__DisplayClass46.b__3f()+ 452 System.Web.Mvc.Async。<> c__DisplayClass46.b__3f()+ 452 System.Web.Mvc.Async。<> c__DisplayClass46.b__3f()+ 452 System.Web.Mvc.Async。<> c__DisplayClass33.b__32(IAsyncResult asyncResult)+15 System.Web.Mvc.Async。<> c__DisplayClass2b.b__1c()+37 System.Web.Mvc.Async。<> c__DisplayClass21.b__1e(IAsyncResult asyncResult)+241 System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult,ExecuteCoreState innerState)+29 System.Web.Mvc.Async.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult) +111 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53 System.Web.Mvc.Async.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult)+19 System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult,ProcessRequestState innerState)+51 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)+111 System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar)+282
我能够缩小它在这条线上的位置:
var token = await Flow.ExchangeCodeForTokenAsync(UserId, authorizationCode.Code, returnUrl,
taskCancellationToken).ConfigureAwait(false);
对于Context,这里是包含类:
[AuthorizationCodeActionFilter]
public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
{
protected new IAuthorizationCodeFlow Flow { get { return FlowData.Flow; } }
protected new string UserId
{ get { return FlowData.GetUserId(this); } }
[AsyncTimeout(60000)]
public async override Task<ActionResult> IndexAsync(AuthorizationCodeResponseUrl authorizationCode,
CancellationToken taskCancellationToken)
{
if (string.IsNullOrWhiteSpace(authorizationCode.Code))
{
var errorResponse = new TokenErrorResponse(authorizationCode);
return OnTokenError(errorResponse);
}
var returnUrl = Request.Url.ToString();
returnUrl = returnUrl.Substring(0, returnUrl.IndexOf("?"));
var token = await Flow.ExchangeCodeForTokenAsync(UserId, authorizationCode.Code, returnUrl,
taskCancellationToken).ConfigureAwait(false);
var oauthState = await AuthWebUtility.ExtracRedirectFromState(Flow.DataStore, UserId,
authorizationCode.State).ConfigureAwait(false);
return new RedirectResult(oauthState);
}
protected override FlowMetadata FlowData
{
get { return new GoogleFlowMetaData(); }
}
protected override ActionResult OnTokenError(TokenErrorResponse errorResponse)
{
throw new TokenResponseException(errorResponse);
}
}
对于其他上下文,这是我的FlowMetaData实现:
public class GoogleFlowMetaData : FlowMetadata
{
public static readonly IAuthorizationCodeFlow flow =
new ForceOfflineGoogleAuthorizationCodeFLow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = ConfigurationManager.AppSettings["Google.ClientID"],
ClientSecret = ConfigurationManager.AppSettings["Google.ClientSecret"]
},
Scopes = new[] {
Scope.UserinfoProfile,
Scope.UserinfoEmail
},
DataStore = new GoogleDataStore(new DBContext())
});
public override string GetUserId(Controller controller)
{
var user = controller.User.Identity;
if (controller.User.Identity.IsAuthenticated)
{
return controller.User.Identity.GetUserId();
}
var userId = (string)controller.Session["google_userId"];
if (string.IsNullOrWhiteSpace(userId))
{
userId = Guid.NewGuid().ToString();
controller.Session["google_userId"] = userId;
}
return userId;
}
public override IAuthorizationCodeFlow Flow
{
get { return flow; }
}
internal class ForceOfflineGoogleAuthorizationCodeFLow : GoogleAuthorizationCodeFlow
{
public ForceOfflineGoogleAuthorizationCodeFLow(GoogleAuthorizationCodeFlow.Initializer initializer)
: base(initializer)
{
}
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
{
var ss = new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl));
ss.AccessType = "offline";
ss.ApprovalPrompt = "force";
ss.ClientId = ClientSecrets.ClientId;
ss.Scope = string.Join(" ", Scopes);
ss.RedirectUri = redirectUri;
return ss;
}
}
}
使用的Nuget包:
其他注意事项:
有关如何解决此问题的任何建议或想法? 如果有任何其他信息有帮助,请告知我们。
答案 0 :(得分:1)
将解决方案迁移到Azure,而不是将其托管在我自己的服务器上,并解决了问题。