【问题标题】:Authenticate with either a token or Open ID Connect in ASP.NET Core 2在 ASP.NET Core 2 中使用令牌或 Open ID Connect 进行身份验证
【发布时间】:2018-06-14 19:13:10
【问题描述】:

类似于应用如何通过内置表单或外部身份提供者提供身份验证,我希望我的网站有两个身份验证选项;在这种情况下,在 Authorization 标头中传递的自定义令牌(例如 API 密钥)将在验证后使用,如果未找到或无效,则打开 ID Connect。任何一个的 Cookie Auth 都将保持一个会话。

我可以单独工作,但是如何将它们结合起来以实现上述目标?

以下是单独的实现。

在 Startup.cs 的 Configure 方法中都有 app.UseAuthentication();

Open ID 实现在 Startup.cs 中的 ConfigureServices 方法中只有以下内容,以及我想要验证的每个控制器方法上的 [Authorize] 属性:

services.AddAuthorization(options =>
{
    options.AddPolicy(OpenIdConnectDefaults.AuthenticationScheme, policy =>
        policy.RequireClaim(ClaimTypes.Authentication, OpenIdConnectDefaults.AuthenticationScheme));
    options.AddPolicy(CookieAuthenticationDefaults.AuthenticationScheme, policy =>
        policy.RequireClaim(ClaimTypes.Authentication, CookieAuthenticationDefaults.AuthenticationScheme));
});

services.AddAuthentication(o =>
{
    o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(o =>
{
    o.LoginPath = "/security/accessdenied";
    o.AccessDeniedPath = "/security/accessdenied";
})
.AddOpenIdConnect(o =>
{
    o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    o.ClientId = oidcClientId;
    o.Authority = oidcAuthority;
    o.Scope.Add("openid");
    o.Scope.Add("profile");
    o.Scope.Add("email");
    o.TokenValidationParameters = new TokenValidationParameters
    {
        // Set what is populated in User.Identity.Name
        NameClaimType = ClaimTypes.Email
    };
});

Open ID Connect 实施到此结束。

对于自定义 SAS 令牌实现,有几部分... 我有一个自定义的AuthenticationHandler,如下所示:

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

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // get token and parse
        // ...

        if (tokenExists)
        {
            // verify token
            // ...

            if (isVerifiedAndCurrent)
            {
                var identity = new ClaimsIdentity(new[] {
                    new Claim(ClaimTypes.Authentication, SasTokenAuthOptions.Scheme)
                });

                var claimsPrincipal = new ClaimsPrincipal(identity);
                result = AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, SasTokenAuthOptions.Scheme));

                // Create cookie
                var authProperties = new AuthenticationProperties()
                {
                    ExpiresUtc = DateTime.UtcNow.AddDays(10)
                };
                await Context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, authProperties);
            }
            else
            {
                result = AuthenticateResult.Fail("Could not verify signed data");
            }
        }

        return await Task.FromResult(result);
    }
}

在 Startup.cs 文件中:

services.AddScheme<SasTokenAuthOptions, SasTokenAuthHandler>(SasTokenAuthOptions.Scheme, options =>
{
    var provider = services.BuildServiceProvider();
    options.Logger = provider.GetService<Serilog.ILogger>();
    options.SasTokenService = provider.GetService<SasTokenService>();
    options.CustomApiAuthSettings = provider.GetService<SasTokenAuthSettings>();
});
services.AddAuthorization(options =>
{
    options.AddPolicy(SasTokenAuthOptions.Scheme, policy => 
        policy.RequireClaim(ClaimTypes.Authentication, SasTokenAuthOptions.Scheme));
    options.AddPolicy(CookieAuthenticationDefaults.AuthenticationScheme, policy =>
        policy.RequireClaim(ClaimTypes.Authentication, CookieAuthenticationDefaults.AuthenticationScheme));
});
services.AddAuthentication(o =>
{
    o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    o.DefaultAuthenticateScheme = SasTokenAuthOptions.Scheme;
})
.AddCookie(o =>
{
    o.LoginPath = "/security/accessdenied";
    o.AccessDeniedPath = "/security/accessdenied";
})

并且在每个控制器方法上我都需要验证:

[Authorize(SasTokenAuthOptions.Scheme)]

也许需要注意:我注意到如果我只有 [Authorize],那么 SAS 令牌身份验证不起作用,但我不确定为什么。

自定义 SAS 令牌实现到此结束。

我尝试在Startup.cs 中添加两组代码,但始终使用 Open ID Connect。

【问题讨论】:

  • 我强烈推荐 Dominick Baier 和 Brock Allen 的 Identity Server 4:github.com/IdentityServer/IdentityServer4。这可能拥有您需要的一切,甚至更多。
  • @cloudstrifebro 这个网络应用不想成为身份提供者,它试图提供一个替代的身份验证选项。

标签: c# asp.net authentication asp.net-core asp.net-core-2.0


【解决方案1】:

Authorize 构造函数采用策略名称,但您需要自定义身份验证。 使用 AuthenticationSchemes 属性

更新: 试试这个

[Authorize(AuthenticationSchemes= SasTokenAuthOptions.Scheme)]

【讨论】:

  • 没看懂,能不能举个例子详细说明一下?
  • 抱歉来晚了,你还在工作还是找到工作了?
  • 我还不能同时实现。
【解决方案2】:

所有的身份验证处理程序代码都与问题中的代码不同,但一旦更正,然后按照指定的here 配置身份验证服务,而不是使用策略。也就是说,不要包含默认方案,而是使用逗号分隔在 Authorize 属性中指定所有方案。例如。

[Authorize(AuthenticationSchemes = AuthSchemes)]
public class MixedController : Controller
    private const string AuthSchemes = CookieAuthenticationDefaults.AuthenticationScheme + "," + JwtBearerDefaults.AuthenticationScheme + "," + OpenIdConnectDefaults.AuthenticationScheme;

我注意到您要挑战用户的方案(例如重定向)应该是最后一个。

【讨论】:

    猜你喜欢
    • 2017-12-23
    • 2022-01-06
    • 1970-01-01
    • 2021-04-29
    • 2021-12-17
    • 2015-05-16
    • 2017-05-17
    • 2019-07-13
    • 2019-06-28
    相关资源
    最近更新 更多