C# ASN.NET Core 2.0 Facebook身份验证外部登录GNINASync失败(不允许)

C# ASN.NET Core 2.0 Facebook身份验证外部登录GNINASync失败(不允许),c#,asp.net-core,asp.net-core-2.0,asp.net-core-identity,C#,Asp.net Core,Asp.net Core 2.0,Asp.net Core Identity,我正在使用Ddentity在ASP.NET Core 2.0中创建一个新的应用程序。我已根据启用Facebook身份验证 当前正在运行的流如下所示: 当新用户从facebook进行身份验证时,应用程序会要求发送电子邮件以用于该应用程序 当用户提供电子邮件时,将在my dbo.AspNetUsers表中创建一个用户,其中包含用户提供的电子邮件,并在my dbo.AspNetUserLogins中创建一个新行,其中包含对提供者、providerKey和用户ID的引用 此时,我可以看到数据库中的所有行

我正在使用Ddentity在ASP.NET Core 2.0中创建一个新的应用程序。我已根据启用Facebook身份验证

当前正在运行的流如下所示:

  • 当新用户从facebook进行身份验证时,应用程序会要求发送电子邮件以用于该应用程序
  • 当用户提供电子邮件时,将在my dbo.AspNetUsers表中创建一个用户,其中包含用户提供的电子邮件,并在my dbo.AspNetUserLogins中创建一个新行,其中包含对提供者、providerKey和用户ID的引用
  • 此时,我可以看到数据库中的所有行都有正确的数据
  • 现在,当用户注销并尝试在某个时候再次使用facebook登录时,应用程序将检查用户是否可以通过以下方式使用提供商凭据登录:

    // Sign in the user with this external login provider if the user already has a login.
    var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
    
    此时,我的结果为NotAllowed(attributeisnotallowed=true),它要求用户输入一封新电子邮件(就像新用户的原始流一样)。当然,电子邮件已经注册,用户不能创建新帐户,因为他不应该创建新帐户

    ExternalLoginCallback的我的控制器是项目的默认实现

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
        {
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return RedirectToAction(nameof(Login));
            }
            var info = await _signInManager.GetExternalLoginInfoAsync();
            if (info == null)
            {
                return RedirectToAction(nameof(Login));
            }
    
            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
            if (result.Succeeded)
            {
                _logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
                return RedirectToLocal(returnUrl);
            }
            if (result.IsLockedOut)
            {
                return RedirectToAction(nameof(Lockout));
            }
            else
            {
                // If the user does not have an account, then ask the user to create an account.
                ViewData["ReturnUrl"] = returnUrl;
                ViewData["LoginProvider"] = info.LoginProvider;
                var email = info.Principal.FindFirstValue(ClaimTypes.Email);
                return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
            }
        }
    
    [HttpGet]
    [异名]
    公共异步任务ExternalLoginCallback(string returnUrl=null,string remoteError=null)
    {
    if(remoteError!=null)
    {
    ErrorMessage=$“来自外部提供程序的错误:{remoteError}”;
    返回重定向到操作(名称(登录));
    }
    var info=await _signInManager.getexternallogininfosync();
    if(info==null)
    {
    返回重定向到操作(名称(登录));
    }
    //如果用户已经登录,请使用此外部登录提供程序登录该用户。
    var result=await _signInManager.externalLoginIgninaSync(info.LoginProvider,info.ProviderKey,isPersistent:false,bypassTwoFactor:true);
    if(result.successed)
    {
    _logger.LogInformation(“用户使用{Name}提供程序登录。”,info.LoginProvider);
    返回重定向到本地(returnUrl);
    }
    如果(结果IsLockedOut)
    {
    返回重定向到操作(名称(锁定));
    }
    其他的
    {
    //如果用户没有帐户,请要求用户创建帐户。
    ViewData[“ReturnUrl”]=ReturnUrl;
    ViewData[“LoginProvider”]=info.LoginProvider;
    var email=info.Principal.FindFirstValue(ClaimTypes.email);
    返回视图(“ExternalLogin”,新的ExternalLoginViewModel{Email=Email});
    }
    }
    

    有谁能帮我找到我遗漏了什么,或者我应该看到什么才能得到答案?提前谢谢。

    是不允许的。
    设置为
    true
    ,如果您已将或设置为
    true
    打开(通常配置为的一部分),但电子邮件地址或电话号码尚未确认

    如果不希望外部登录需要确认的电子邮件或电话号码,可以在首次创建
    IdentityUser
    派生类后,在创建该类时设置相关属性。e、 g:

    var identityUser = new IdentityUser
    {
        // ...
        EmailConfirmed = true,
        PhoneNumberConfirmed = true
    };
    
    否则,如果您确实希望验证过程发生,您可以按照ASP.NET Core中有关电子邮件地址方面的指南进行操作

    你可以看到这一切是如何运作的。你最终会:

    实现如下所示(删除日志记录):

    公共虚拟异步任务CanSignInAsync(TUser用户)
    {
    如果(选项签名要求)重新确认邮件&&
    !(等待UserManager.IsEmailConfirmedAsync(用户)))
    {
    返回false;
    }
    如果(Options.SignIn.Required)需要重新确认电话号码&&
    !(等待UserManager.IsPhoneNumberConfirmedAsync(用户)))
    {
    返回false;
    }
    返回true;
    }
    
    if (!await CanSignInAsync(user))
    {
        return SignInResult.NotAllowed;
    }
    
    public virtual async Task<bool> CanSignInAsync(TUser user)
    {
        if (Options.SignIn.RequireConfirmedEmail &&
            !(await UserManager.IsEmailConfirmedAsync(user)))
        {
            return false;
        }
    
        if (Options.SignIn.RequireConfirmedPhoneNumber &&
            !(await UserManager.IsPhoneNumberConfirmedAsync(user)))
        {
            return false;
        }
    
        return true;
    }