MVC 5 Owin Facebook Auth导致Null参考异常

Gra*_*cie 27 asp.net-mvc facebook owin asp.net-mvc-5 asp.net-identity

我正在尝试在Visual Studio 2013中的新MVC 5项目中设置集成的OWIN Facebook身份验证.我已根据本教程配置了应用程序和密钥:

http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on

但是,我在AccountController中从此调用中抛出了NullReferenceException:

    [AllowAnonymous]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
Run Code Online (Sandbox Code Playgroud)

我已经检查了Fiddler的回复,并且得到了Facebook的成功回复,但仍然得到了这个错误.响应如下:

{"id":"xxx","name":"xxx","first_name":"xxx","last_name":"xxx","link":
"https:\/\/www.facebook.com\/profile.php?id=xxx","location":{"id":"xxx","name":"xxx"},
"gender":"xxx","timezone":1,"locale":"en_GB","verified":true,"updated_time":"2013-10-23T10:42:23+0000"}
Run Code Online (Sandbox Code Playgroud)

我在http和https中进行调试时得到了这个.我猜这是一个框架错误,但迄今为止通过反射器诊断出这一点.

Hon*_*Sun 26

这可能是身份OWIN扩展代码中的一个错误.我无法重现这个问题,因为我的facebook有效负载总是在json中返回一个用户名字段,这在你的fb响应中是丢失的.我不太确定为什么它不存在.

身份owin扩展方法中的代码没有对身份名称声明进行空检查,该声明与用户名字段相同.我们已在内部提交了一个错误.

为了解决此问题,您是否可以尝试使用以下代码替换ExternalLoginCallback方法:

   [AllowAnonymous]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var result = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);
        if (result == null || result.Identity == null)
        {
            return RedirectToAction("Login");
        }

        var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier);
        if (idClaim == null)
        {
            return RedirectToAction("Login");
        }

        var login = new UserLoginInfo(idClaim.Issuer, idClaim.Value);
        var name = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", "");

        // Sign in the user with this external login provider if the user already has a login
        var user = await UserManager.FindAsync(login);
        if (user != null)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToLocal(returnUrl);
        }
        else
        {
            // If the user does not have an account, then prompt the user to create an account
            ViewBag.ReturnUrl = returnUrl;
            ViewBag.LoginProvider = login.LoginProvider;
            return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = name });
        }
    }
Run Code Online (Sandbox Code Playgroud)

当没有来自facebook/google的用户名时,代码会将默认用户名设置为空.

  • 这会解决问题,但是我现在在方法中创建用户名时得到NullReferenceException:public async Task <ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model,string returnUrl)at the line:var info = await AuthenticationManager.GetExternalLoginInfoAsync() (2认同)

小智 24

孙红叶在上面的回答中做了所有繁重的工作.

这里有一些代码可以添加到您的控制器类中,并代替麻烦的AuthenticationManager.GetExternalLoginInfoAsync()来调用.

private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_Workaround()
{
    ExternalLoginInfo loginInfo = null;

    var result = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);

    if (result != null && result.Identity != null)
    {
        var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier);
        if (idClaim != null)
        {
            loginInfo = new ExternalLoginInfo()
            {
                DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""),
                Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value)
            };
        }
    }
    return loginInfo;
}
Run Code Online (Sandbox Code Playgroud)