回购这里 –

RemoteAuthenticationHandler我有一个准备在其基础上进行构建的基本框架,但我无法弄清楚究竟HandleRemoteAuthenticateAsync应该怎么做才能使其工作。

using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text.Encodings.Web;

namespace BlazorAuthExample;

public class MyAuthOptions : RemoteAuthenticationOptions
{
    public MyAuthOptions()
    {
        CallbackPath = new PathString("/signin-myauth");
    }
}

public class MyAuthHandler : RemoteAuthenticationHandler<MyAuthOptions>
{
    public MyAuthHandler(
        IOptionsMonitor<MyAuthOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder) : base(options, logger, encoder)
    {
    }

    protected override Task HandleChallengeAsync(AuthenticationProperties properties)
    {
        Context.Response.Redirect("/my-sign-in-page");
        return Task.CompletedTask;
    }

    protected override Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
    {
        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, "myauth");
        return Task.FromResult(HandleRequestResult.Success(ticket));
    }
}

  1. 创建一个新的 Blazor Web 应用程序,并指定“个人账户”作为身份验证类型。
  2. 添加上述类
  3. Program.cs查找
builder.Services.AddAuthentication(options =>
    {
        options.DefaultScheme = IdentityConstants.ApplicationScheme;
        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
    })
    .AddIdentityCookies();

并将其更改为

builder.Services.AddAuthentication(options =>
    {
        options.DefaultScheme = IdentityConstants.ApplicationScheme;
        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
    })
    .AddRemoteScheme<MyAuthOptions, MyAuthHandler>("myauth", "My auth", null)
    .AddIdentityCookies();
  1. MySignInPage.razor创建包含以下内容的文件
@page "/my-sign-in-page"
<form action="/signin-myauth" method="post">
   <button type="submit">Click here to sign in</button>
</form>
  1. 运行应用
  2. 点击Register左侧导航菜单中的项目
  3. 在“使用其他服务注册”下点击My auth
  4. 点击“单击此处登录”按钮

我现在期望看到与登录 Google 等时相同的行为,但似乎什么都没有发生。


最佳答案
1

您未RedirectUri在您的处理程序中进行处理。

将这两行添加到您的HandleRemoteAuthenticateAsync方法中。

// hardcoded for sake of simplicity
ticket.Properties.RedirectUri = "/Account/ExternalLogin?ReturnUrl=&Action=LoginCallback";
ticket.Properties.Items.Add("LoginProvider", "myauth");

理想情况下,您必须将 RedirectUri 从质询方法 ( properties.RedirectUri) 传递到您的登录页面,然后再传递到您的处理方法。

更新:

以下是支持正确处理的示例实现RedirectUri。请勿在生产中使用它。

public class MyAuthHandler : RemoteAuthenticationHandler<MyAuthOptions>
{
    public MyAuthHandler(
        IOptionsMonitor<MyAuthOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder) : base(options, logger, encoder)
    {
    }

    protected override Task HandleChallengeAsync(AuthenticationProperties properties)
    {
        var url = "/my-sign-in-page?RedirectUri=" + Uri.EscapeDataString(properties.RedirectUri ?? "");

        if (properties.Items.TryGetValue("XsrfId", out var xsrfId))
        {
            url += "&xsrfId=" + xsrfId;
        }

        Context.Response.Redirect(url);

        return Task.CompletedTask;
    }

    protected override Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
    {
        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, "myauth");

        ticket.Properties.RedirectUri = Context.Request.Form["RedirectUri"];
        ticket.Properties.Items.Add("LoginProvider", "myauth");
        if (Context.Request.Form.TryGetValue("XsrfId", out var xsrfId))
        {
            ticket.Properties.Items.Add("XsrfId", xsrfId);
        }

        return Task.FromResult(HandleRequestResult.Success(ticket));
    }
}
@page "/my-sign-in-page"
<form action="/signin-myauth" method="post">
    <input type="hidden" name="RedirectUri" value="@RedirectUri"/>
    <input type="hidden" name="XsrfId" value="@XsrfId"/>
    <button type="submit">Click here to sign in</button>
</form>

@code {

    [SupplyParameterFromQuery]
    private string? RedirectUri { get; set; }

    [SupplyParameterFromQuery]
    private string? XsrfId { get; set; }

}

3

  • 谢谢,Mike!看起来这已经是解决方案的 99%,但似乎还缺少一些东西。我添加了 Google 和 LinkedIn,然后在 Google 上创建了一个新帐户。然后我可以转到 /Account/Manage/ExternalLogins 并添加 LinkedIn,它会将其与登录帐户关联。但当我单击“我的身份验证”时,它会尝试创建一个新帐户 – 您知道缺少什么吗?


    – 

  • @PeterMorris,这是因为我RedirectUri对寄存器进行了硬编码。要使其完全发挥作用,您必须RedirectUri正确处理。


    – 


  • @PeterMorris,我更新了我的答案以展示完整流程的示例RedirectUri


    –