我有一个项目在工作,我需要使用谷歌和微软帐户登录 . 到目前为止它在本地主机上应该工作,但是 SignInManager<IdentityUser>.ExternalLoginSignInAsync 在服务器上部署时以相同的方式失败 . 用户通过外部登录对话框就像它工作但在回调中失败一样 .

除了"Failed"之外, SignInResult 没有提供任何解释 . 请注意,如果我错过了至关重要的事情,这是我第一次感到惊讶 . 该站点不使用自动生成的登录页面 .

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<IISOptions>(options =>
        {
            options.ForwardClientCertificate = false;
        });

        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddAuthentication().AddGoogle(options =>
        {
            options.ClientId = Configuration["Authentication:Google:ClientId"];
            options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
        });

        services.AddAuthentication().AddMicrosoftAccount(options =>
        {
            options.ClientId = Configuration["Authentication:Microsoft:ClientId"];
            options.ClientSecret = Configuration["Authentication:Microsoft:ClientSecret"];
        });

        services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(SqlConfigurationDatabase.Credentials));

        services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapRoute(name: "add", template: "{controller=Product}/{action=Add}");
        });
    }
}

编辑:我忘了包含其余的登录代码 . 至于标记:

<form asp-controller="Home" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" target="_blank" class="form-horizontal">
@{
    foreach (var provider in await SignInManager.GetExternalAuthenticationSchemesAsync())
    {
        var name = provider.DisplayName + ".png";
        <button type="submit" name="provider" value="@provider.DisplayName" title="Log in using your @provider.DisplayName account">
            <img src="~/images/@name" />
            @provider.DisplayName
        </button>
    }
}
</form>

Home控制器是唯一与外部登录服务通信的控制器 .

public class HomeController : Controller
{
    private readonly UserManager<IdentityUser> users;

    private readonly SignInManager<IdentityUser> signIn;

    public HomeController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
    {
        users = userManager;
        signIn = signInManager;
    }

    public IActionResult Index()
    {
        if (signIn.IsSignedIn(User))
            return RedirectToLocal("/Product/Abc123");

        return View();
    }

    public IActionResult Gdpr()
    {
        return View();
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public IActionResult ExternalLogin(string provider, string returnUrl = null)
    {
        var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Home", new { ReturnUrl = returnUrl });
        var properties = signIn.ConfigureExternalAuthenticationProperties(provider, redirectUrl);

        return Challenge(properties, provider);
    }

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
        if (remoteError != null)
        {
            ModelState.AddModelError("", $"Error from external provider: {remoteError}");

            return RedirectToAction(nameof(HomeController.Index), "Home");
        }

        var info = await signIn.GetExternalLoginInfoAsync();
        if (info == null)
            return RedirectToLocal(returnUrl);

        var result = await signIn.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
        if (result.Succeeded)
            return RedirectToLocal(returnUrl);
        else
            return RedirectToLocal(returnUrl);
    }

    private IActionResult RedirectToLocal(string returnUrl)
    {
        if (Url.IsLocalUrl(returnUrl))
            return Redirect(returnUrl);
        else
            return RedirectToAction(nameof(HomeController.Index), "Home");
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Logout()
    {
        await signIn.SignOutAsync();

        return RedirectToAction(nameof(HomeController.Index), "Home");
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}

目前没有负载 balancer ,群集,Web场或任何其他花哨的东西 . 我基本上只是调整了Visual Studio创建的示例站点(ASP.NET Core 2.1 Web应用程序,其身份验证设置为个人用户帐户) .