You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义RemoteAuthenticationHandler无法实现登录的问题求助

问题分析

你当前的实现缺少外部认证流程中关键的认证属性传递和Identity外部登录的回调衔接,导致点击登录按钮后无法触发后续的本地账号关联流程。具体问题点:

  • HandleChallengeAsync直接硬编码跳转,丢失了Identity传递的returnUrl、state等关键认证属性
  • 自定义登录页的表单没有携带这些必要属性,回调到/signin-myauth时无法完成认证上下文的衔接
  • HandleRemoteAuthenticateAsync没有关联原有的AuthenticationProperties,导致认证成功后无法正确跳转到目标页面并触发Identity的外部登录逻辑
修复步骤

1. 修改HandleChallengeAsync,传递认证属性

更新MyAuthHandler中的HandleChallengeAsync方法,将原有的认证属性编码后传递到自定义登录页:

using Microsoft.AspNetCore.WebUtilities;

// ...

protected override Task HandleChallengeAsync(AuthenticationProperties properties)
{
    // 将认证属性编码为查询参数
    var query = QueryHelpers.AddQueryString("/my-sign-in-page", properties.Items);
    // 添加returnUrl参数(如果存在)
    if (!string.IsNullOrEmpty(properties.RedirectUri))
    {
        query = QueryHelpers.AddQueryString(query, "returnUrl", properties.RedirectUri);
    }
    Context.Response.Redirect(query);
    return Task.CompletedTask;
}

2. 更新自定义登录页,携带认证属性

修改MySignInPage.razor,接收并在表单中携带state和returnUrl等属性:

@page "/my-sign-in-page"

@code {
    [SupplyParameterFromQuery]
    public string? state { get; set; }

    [SupplyParameterFromQuery]
    public string? returnUrl { get; set; }
}

<form action="/signin-myauth" method="post">
    @if (!string.IsNullOrEmpty(state))
    {
        <input type="hidden" name="state" value="@state" />
    }
    @if (!string.IsNullOrEmpty(returnUrl))
    {
        <input type="hidden" name="returnUrl" value="@returnUrl" />
    }
    <button type="submit">Click here to sign in</button>
</form>

3. 完善HandleRemoteAuthenticateAsync,关联认证属性

更新HandleRemoteAuthenticateAsync方法,从请求中获取state和returnUrl,并关联到AuthenticationTicket的属性中:

protected override Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
{
    // 从请求中获取state和returnUrl参数
    var state = Request.Form["state"].FirstOrDefault();
    var returnUrl = Request.Form["returnUrl"].FirstOrDefault();

    // 创建包含跳转信息的认证属性
    var properties = new AuthenticationProperties
    {
        RedirectUri = returnUrl,
        Items = { ["state"] = state }
    };

    // 创建身份凭证
    var nameIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, "mrpmorris@gmail.com", ClaimTypes.NameIdentifier, "myauth", "myauth");
    var identity = new ClaimsIdentity([nameIdentifierClaim], "myauth");
    var principal = new ClaimsPrincipal(identity);

    // 创建包含属性的认证票据
    var ticket = new AuthenticationTicket(principal, properties, "myauth");
    return Task.FromResult(HandleRequestResult.Success(ticket));
}

4. 确认Program.cs的认证配置

当前配置已满足需求,若需要明确指定默认挑战方案(可选),可补充如下:

builder.Services.AddAuthentication(options =>
    {
        options.DefaultScheme = IdentityConstants.ApplicationScheme;
        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
        options.DefaultChallengeScheme = "myauth"; // 可选,指定默认挑战用自定义方案
    })
    .AddRemoteScheme<MyAuthOptions, MyAuthHandler>("myauth", "My auth", null)
    .AddIdentityCookies();
验证流程
  1. 重新运行应用,点击"Register"进入注册页面
  2. 点击"My auth"按钮,会跳转到自定义登录页,URL中会包含state和returnUrl参数
  3. 点击"Click here to sign in"按钮,表单携带参数提交到/signin-myauth
  4. 认证成功后会自动跳转到Identity的外部登录回调页面,引导完成本地账号关联(或直接登录,若账号已存在)

内容的提问来源于stack exchange,提问作者Peter Morris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:22:46