请考虑 program.cs 中的以下代码:
var builder = WebApplication.CreateBuilder(args);
//omit some builder settings
builder.Services.AddAuthentication(options =>
{
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    options.LoginPath = "/signin";
    options.LogoutPath = "/signout";
})
.AddOAuth("Discord", options =>
{
    options.AuthorizationEndpoint = "https://discord.com/api/oauth2/authorize";
    options.Scope.Add("identify");
    options.Scope.Add("email");
    options.CallbackPath = new PathString("/Account/LoginCallback");
    options.ClientId = "some id";
    options.ClientSecret = "some secret";
    options.TokenEndpoint = "https://discord.com/api/oauth2/token";
    options.UserInformationEndpoint = "https://discord.com/api/users/@me";
    options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
    options.ClaimActions.MapJsonKey(ClaimTypes.Name, "username");
    options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
    options.ClaimActions.MapCustomJson("urn:discord:avatar:url", user =>
        string.Format(
            CultureInfo.InvariantCulture,
            "https://cdn.discordapp.com/avatars/{0}/{1}.{2}",
            user.GetString("id"),
            user.GetString("avatar"),
            user.GetString("avatar")!.StartsWith("a_") ? "gif" : "png"));
    options.AccessDeniedPath = "/Account/LoginFailed";
    options.Events = new OAuthEvents
    {
        OnCreatingTicket = async context =>
        {
            var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
            var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
            var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
            context.RunClaimActions(user);
        }
    };
});
以下是我的帐户控制器内:
[HttpGet("~/signin")]
public async Task<IActionResult> SignIn() => View("SignIn", await HttpContext.GetExternalProvidersAsync());
[HttpPost("~/signin")]
public async Task<IActionResult> SignIn([FromForm] string provider)
{
    if (string.IsNullOrWhiteSpace(provider))
    {
        return BadRequest();
    }
    if (!await HttpContext.IsProviderSupportedAsync(provider))
    {
        return BadRequest();
    }
    return Challenge(new AuthenticationProperties {RedirectUri = "/Account/LoginCallback" }, provider);
}
[HttpGet("~/signout")]
[HttpPost("~/signout")]
public IActionResult SignOutCurrentUser()
{
    return SignOut(new AuthenticationProperties {RedirectUri = "/"},
        CookieAuthenticationDefaults.AuthenticationScheme);
}
[HttpGet]
public IActionResult LoginCallback()
{
    return RedirectToAction("Index", "Home");
}
上面的代码有效。会发生以下情况:
- 我点击 LoginViaDiscord 按钮
- 调用 SignIn post 方法
- 我被重定向到不和谐
- 我通过不和谐登录
- 我被重定向回 LoginCallback
当我查看网站时,我已经完全登录。问题是我跳过了记录用户并创建帐户的整个数据库步骤。
当我使用 MVC 5 进行类似的身份验证时,我将有一个回调操作方法,并且该回调方法将完成所有设置。创建用户,围绕用户执行逻辑,然后登录。但是,使用此代码,我已经完全登录,并且没有涉及数据库步骤。
我的问题是当挑战返回到 LoginCallback 时如何正确完成与上述相同但不登录的操作,以及如何从 LoginCallback 操作中的不和谐中检索信息?我想在允许用户登录之前对用户执行一些逻辑,并且我还想确保他们的帐户是在数据库中创建的。