我正在使用 Asp.Net MVC 5 并利用 Microsoft 的 Identity (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);
在我发布 facebook 登录表单的 Controller 函数中,
[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) 我该如何解决这个问题?
谢谢。