【发布时间】: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