MVC5 和 OWIN facebook 身份验证提供程序在 IE11 和 Firefox 中不工作(但在 Chrome 中工作)
MVC5 and OWIN facebook authentication provider not working in IE11 and Firefox (but works in Chrome)
我正在使用 Asp.Net MVC 5 并利用 Microsoft 的身份 (v2) 实现进行身份验证和外部 (facebook) 登录。
我的外部登录代码是这样的:
在 Startup.Auth.cs 我声明提供者:
var facebookAuthenticationOptions = new FacebookAuthenticationOptions();
facebookAuthenticationOptions.Scope.Add("email");
(...)
facebookAuthenticationOptions.AppId = "<my fb app id>";
facebookAuthenticationOptions.AppSecret = "<my fb app secret>";
facebookAuthenticationOptions.Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
//Get the access token from FB and store it in the database
context.Identity.AddClaim(
new System.Security.Claims.Claim("FacebookAccessToken",
context.AccessToken));
}
};
app.UseFacebookAuthentication(facebookAuthenticationOptions);
在我 post facebook 登录表单的控制器函数中,
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
returnUrl = !String.IsNullOrEmpty(returnUrl) ? returnUrl : "/";
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
return null;
}
在我的基本控制器中使用这个(我从中派生出所有控制器),我使用 owin OAuth:
internal class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri)
: this(provider, redirectUri, null)
{
}
public ChallengeResult(string provider, string redirectUri, string userId)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
然后我通过外部回调函数获得回调(正如我在上面的 ChallangeResult 对象中声明的那样):
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// Sign in the user with this external login provider if the user already has a login
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
// login logic code here.
// and return some View(""); or RedirerctToAction("somewhere");
}
}
另外值得注意的是,我正在使用 StructureMap 3.0 进行依赖注入,并且根据以下代码,它将任何控制器代码的生命周期限制为请求的生命周期。
public void Init(HttpApplication context) {
context.BeginRequest += (sender, e) => StructuremapMvc.StructureMapDependencyScope.CreateNestedContainer();
context.EndRequest += (sender, e) => {
HttpContextLifecycle.DisposeAndClearAll();
StructuremapMvc.StructureMapDependencyScope.DisposeNestedContainer();
};
}
现在,这一切都很好,当我 运行 来自 chrome 的应用程序时,它确实为我处理了 facebook 登录。但是当我使用 Internet Explorer(尝试过 11)或 Firefox 时,它在 /{controller}/ExternalLogin 处挂在黑屏中并且不进行任何重定向。
如果这是 IOC 包含结构图的问题,我相信它也不应该在 chrome 上顺利地 运行。所以我一直在网上搜索,但找不到解决方案 - 或任何关于正在发生的事情的迹象。而且由于我没有得到任何异常之类的信息,所以我无法弄清楚我做错了什么。
总结一下:
- 我正在使用:ASP.NET MVC 5 + OWIN (v3.0.1) + Identity (v2) + StructureMap 3 + Facebook 登录
- 这一切都很好,并且在 chrome
中完成了工作
- 在 IE11 或 Firefox 中不起作用
- 我的问题是 (1) 为什么? (2) 我该如何解决这个问题?
谢谢。
好吧,我想的有点太复杂了。问题出在我正在 posting 的输入标签中。
如果您的 post 操作采用 public ActionResult ExternalLogin(string provider, string returnUrl)
之类的表单数据(即无模型),并且您使用输入图像的名称和值来提供该表单操作,例如:
<input type="image" id="@facebookLogin.AuthenticationType" name="provider" value="@facebookLogin.AuthenticationType"...>
然后,出于某种原因 Chrome 发送正确的 post 数据,而 Internet Explorer 和 Firefox 不能。
所以没有依赖注入、中间件或 OAuth 问题,只是普通的旧 html 这个问题。
我正在使用 Asp.Net MVC 5 并利用 Microsoft 的身份 (v2) 实现进行身份验证和外部 (facebook) 登录。
我的外部登录代码是这样的:
在 Startup.Auth.cs 我声明提供者:
var facebookAuthenticationOptions = new FacebookAuthenticationOptions();
facebookAuthenticationOptions.Scope.Add("email");
(...)
facebookAuthenticationOptions.AppId = "<my fb app id>";
facebookAuthenticationOptions.AppSecret = "<my fb app secret>";
facebookAuthenticationOptions.Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
//Get the access token from FB and store it in the database
context.Identity.AddClaim(
new System.Security.Claims.Claim("FacebookAccessToken",
context.AccessToken));
}
};
app.UseFacebookAuthentication(facebookAuthenticationOptions);
在我 post facebook 登录表单的控制器函数中,
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
returnUrl = !String.IsNullOrEmpty(returnUrl) ? returnUrl : "/";
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
return null;
}
在我的基本控制器中使用这个(我从中派生出所有控制器),我使用 owin OAuth:
internal class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri)
: this(provider, redirectUri, null)
{
}
public ChallengeResult(string provider, string redirectUri, string userId)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
然后我通过外部回调函数获得回调(正如我在上面的 ChallangeResult 对象中声明的那样):
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// Sign in the user with this external login provider if the user already has a login
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
// login logic code here.
// and return some View(""); or RedirerctToAction("somewhere");
}
}
另外值得注意的是,我正在使用 StructureMap 3.0 进行依赖注入,并且根据以下代码,它将任何控制器代码的生命周期限制为请求的生命周期。
public void Init(HttpApplication context) {
context.BeginRequest += (sender, e) => StructuremapMvc.StructureMapDependencyScope.CreateNestedContainer();
context.EndRequest += (sender, e) => {
HttpContextLifecycle.DisposeAndClearAll();
StructuremapMvc.StructureMapDependencyScope.DisposeNestedContainer();
};
}
现在,这一切都很好,当我 运行 来自 chrome 的应用程序时,它确实为我处理了 facebook 登录。但是当我使用 Internet Explorer(尝试过 11)或 Firefox 时,它在 /{controller}/ExternalLogin 处挂在黑屏中并且不进行任何重定向。
如果这是 IOC 包含结构图的问题,我相信它也不应该在 chrome 上顺利地 运行。所以我一直在网上搜索,但找不到解决方案 - 或任何关于正在发生的事情的迹象。而且由于我没有得到任何异常之类的信息,所以我无法弄清楚我做错了什么。
总结一下:
- 我正在使用:ASP.NET MVC 5 + OWIN (v3.0.1) + Identity (v2) + StructureMap 3 + Facebook 登录
- 这一切都很好,并且在 chrome 中完成了工作
- 在 IE11 或 Firefox 中不起作用
- 我的问题是 (1) 为什么? (2) 我该如何解决这个问题?
谢谢。
好吧,我想的有点太复杂了。问题出在我正在 posting 的输入标签中。
如果您的 post 操作采用 public ActionResult ExternalLogin(string provider, string returnUrl)
之类的表单数据(即无模型),并且您使用输入图像的名称和值来提供该表单操作,例如:
<input type="image" id="@facebookLogin.AuthenticationType" name="provider" value="@facebookLogin.AuthenticationType"...>
然后,出于某种原因 Chrome 发送正确的 post 数据,而 Internet Explorer 和 Firefox 不能。
所以没有依赖注入、中间件或 OAuth 问题,只是普通的旧 html 这个问题。