将自定义AuthenticationHandler添加到外部登录提供程序列表

将自定义AuthenticationHandler添加到外部登录提供程序列表,authentication,asp.net-core,asp.net-identity,asp.net-core-authenticationhandler,Authentication,Asp.net Core,Asp.net Identity,Asp.net Core Authenticationhandler,我正在使用ASP.NET Core 3.1,并配置了多个外部登录提供程序: services.AddAuthentication() .AddDeviantArt(d => { d.Scope.Add("feed"); d.ClientId = Configuration["Authentication:DeviantArt:ClientId"]; d.ClientSecret = Configuration["Authenticat

我正在使用ASP.NET Core 3.1,并配置了多个外部登录提供程序:

services.AddAuthentication()
    .AddDeviantArt(d => {
        d.Scope.Add("feed");
        d.ClientId = Configuration["Authentication:DeviantArt:ClientId"];
        d.ClientSecret = Configuration["Authentication:DeviantArt:ClientSecret"];
        d.SaveTokens = true;
    })
    .AddTwitter(t => {
        t.ConsumerKey = Configuration["Authentication:Twitter:ConsumerKey"];
        t.ConsumerSecret = Configuration["Authentication:Twitter:ConsumerSecret"];
        t.SaveTokens = true;
    });
我想创建一个自定义的
AuthenticationProvider
,它不是重定向到另一个网站,而是请求该网站的“API密钥”,并将其视为访问令牌。(该网站不支持OAuth的任何版本。)

在实际连接它之前,我想测试一下是否可以让自定义的
AuthenticationProvider
工作,因此我找到了一个实现HTTP基本身份验证的:

public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> {
    public CustomAuthenticationHandler(
        IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock)
        : base(options, logger, encoder, clock) { }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
        if (!Request.Headers.ContainsKey("Authorization")) {
            return AuthenticateResult.NoResult();
        }

        if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue headerValue)) {
            return AuthenticateResult.NoResult();
        }

        if (!"Basic".Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase)) {
            return AuthenticateResult.NoResult();
        }

        byte[] headerValueBytes = Convert.FromBase64String(headerValue.Parameter);
        string userAndPassword = Encoding.UTF8.GetString(headerValueBytes);
        string[] parts = userAndPassword.Split(':');
        if (parts.Length != 2) {
            return AuthenticateResult.Fail("Invalid Basic authentication header");
        }
        string user = parts[0];
        string password = parts[1];

        bool isValidUser = true;

        if (!isValidUser) {
            return AuthenticateResult.Fail("Invalid username or password");
        }
        var claims = new[] { new Claim(ClaimTypes.Name, user) };
        var identity = new ClaimsIdentity(claims, Scheme.Name);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, Scheme.Name);
        return AuthenticateResult.Success(ticket);
    }

    protected override async Task HandleChallengeAsync(AuthenticationProperties properties) {
        Response.Headers["WWW-Authenticate"] = $"Basic realm=\"Custom realm name here\", charset=\"UTF-8\"";
        await base.HandleChallengeAsync(properties);
    }
}
公共类CustomAuthenticationHandler:AuthenticationHandler{ 公共CustomAuthenticationHandler( IOPTIONS监视器选项, iLogger工厂记录器, URL编码器, ISystemClock(系统时钟) :base(选项、记录器、编码器、时钟){} 受保护的重写异步任务handleAuthenticateAync(){ if(!Request.Headers.ContainsKey(“授权”)){ 返回AuthenticateResult.NoResult(); } if(!AuthenticationHeaderValue.TryParse(Request.Headers[“Authorization”],out AuthenticationHeaderValue headerValue)){ 返回AuthenticateResult.NoResult(); } if(!“Basic”.Equals(headerValue.Scheme、StringComparison.OrdinalIgnoreCase)){ 返回AuthenticateResult.NoResult(); } byte[]headerValueBytes=Convert.FromBase64String(headerValue.Parameter); 字符串userAndPassword=Encoding.UTF8.GetString(headerValueBytes); string[]parts=userAndPassword.Split(“:”); 如果(parts.Length!=2){ 返回AuthenticateResult.Fail(“无效的基本身份验证头”); } 字符串用户=部件[0]; 字符串密码=部件[1]; bool-isValidUser=true; 如果(!isValidUser){ 返回AuthenticateResult.Fail(“无效的用户名或密码”); } var claims=new[{new claims(ClaimTypes.Name,user)}; var标识=新的索赔实体(索赔、方案、名称); var principal=新的ClaimsPrincipal(身份); var票证=新的身份验证票证(主体,Scheme.Name); 返回AuthenticateResult.Success(票证); } 受保护的重写异步任务HandleChallengeAsync(AuthenticationProperties属性){ Response.Headers[“WWW Authenticate”]=“Basic realm=\“Custom realm name here\”,charset=“UTF-8\”; wait base.HandleChallengeAsync(属性); } } 我将此添加到Startup.cs:

.AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>("Test", "Testing", o => { })
.AddScheme(“测试”,“测试”,o=>{})
问题是从未调用
handleAuthenticationAsync
方法。我找到的解决这个问题的其他解决方案通常说,您需要将其设置为“默认”身份验证方案,但我不希望这会干扰其他外部登录提供程序的设置


有没有一种方法可以在不更改默认身份验证方案或向控制器或操作添加其他属性的情况下使其正常工作?

添加
AddAuthentication


services.AddAuthentication(“Test”)
当您添加
AddAuthentication


services.AddAuthentication(“Test”)

这似乎并不能解决“外部登录提供者”场景中的问题。指定默认方案似乎没有任何效果,而且这也不是我们想要的,因为用户需要有多个自定义方案。这似乎无法解决“外部登录提供程序”方案的问题。指定一个默认方案似乎没有任何效果,而且这也不是我们想要的,因为用户需要有多个自定义方案。