0

我正在使用 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) 我该如何解决这个问题?

谢谢。

4

1 回答 1

1

好吧,我想的有点太复杂了。问题出在我发布的输入标签中。

如果您的发布操作采用表单数据public ActionResult ExternalLogin(string provider, string returnUrl)(即没有模型)并且您使用输入图像的名称和值来提供该表单操作,例如:

<input type="image" id="@facebookLogin.AuthenticationType" name="provider" value="@facebookLogin.AuthenticationType"...>

然后,由于某种原因,Chrome 会发送正确的帖子数据,而 Internet Explorer 和 Firefox 则不能。

所以没有依赖注入、中间件或 OAuth 问题,只是简单的旧 html 与这个。

于 2015-06-24T16:57:23.150 回答