Warm tip: This article is reproduced from serverfault.com, please click

c#-在ASP Net Core中实现两个身份验证选项(令牌和证书)

(c# - Implement two authentication options (Token and Certificate) in ASP Net Core)

发布于 2020-06-19 14:15:38

[目标netcoreapp3.1]

你好呀!因此,在Startup.cs中,我有一个受这种形式的中间件保护的Web Api:


public void ConfigureServices(IServiceCollection services)
{
    //other services configuration
    services.AddProtectedWebApi(options => { /* config */};
    //other services configuration
}

这将验证由Azure发行的Jwt令牌,并授予对该API的访问权限;它工作正常。目前,我有一个前端有 Angular 的客户端网站,用户可以在其中通过Azure AD登录。Angular将令牌发送到我的Web API,一切正常。

我现在想使用相同的webapp来处理没有凭证但具有预先提供的客户端证书的用户的查询请求。因此,基本上,我想通过Azure或客户端证书在Angular WebSite上进行身份验证。然后,Angular会将信息跟踪到我的webapp,这将进而使用适当的方法对用户进行身份验证。

需要说明的是,我仍然希望某人能够通过使用其Azure帐户登录而无需证书。

在这种情况下,是否有一种简单的方法就可以拥有两个身份验证选项,而不必创建单独的Web应用程序?我在那儿读了一点:https : //docs.microsoft.com/zh-cn/aspnet/core/security/authentication/certauth?view=aspnetcore-3.1#optional-client-certificates 但似乎只能在我无法使用的ASP.NET Core 5预览版。

Questioner
jimkick3
Viewed
11
jimkick3 2020-06-20 04:14:42

希望接下来的事情能对某人有所帮助!我最终找到了此链接:https : //docs.microsoft.com/zh-cn/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1

它说明了如何实施多个都有成功机会的授权策略。下面是经过更多研究后发现的使用IIS的解决方案:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    //other services configuration
services.Configure<IISOptions>(options =>
            {
                options.ForwardClientCertificate = true;
            });

            services.Configure<CertificateForwardingOptions>(options =>
            {
                options.CertificateHeader = {/*your header present in client request*/};
            });
    //other services configuration
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
            {
                options.AllowedCertificateTypes =/*Whatever you need*/;
                options.Events = new CertificateAuthenticationEvents
                {
                    OnCertificateValidated = context =>
                    {

                        if ({/*CertValidationClass*/}.ValidateCertificate(context.ClientCertificate))
                        {
                            context.Success();
                        }
                        else
                        {
                            context.Fail("invalid cert");
                        }

                        return Task.CompletedTask;
                    }
                };
            });


    services.AddProtectedWebApi(options => { /* config */};
    //other services configuration
}

{CertValidationClass}是定制的服务或帮助程序类,用于验证所有我需要验证才能批准的证书。显然,你可以自己向此模板添加更多验证和操作。

我已经app.UseAuthentication(); app.UseAuthorization();在中间件管道中使用过,无需更改它,但是你必须app.UseCertificateForwarding();在这两个之前添加

现在,我只需要在控制器上方指定要保护的控制器,就可以同时使用两种Authorization方法,就像这样,如果一个方法失败了,它就会落在另一个方法上,并且效果很好,我通过Insomnia发出的请求进行了测试, /无令牌和/无证书。

MyApiController.cs

[Authorize(AuthenticationSchemes = AuthSchemes)]
    public class MyApiController
    {
        //Just add the schemes you want used here
        private const string AuthSchemes =
            CertificateAuthenticationDefaults.AuthenticationScheme; + "," +
            JwtBearerDefaults.AuthenticationScheme;