根据 url 参数选择身份方案
Chose identity scheme based on url parameter
我正在尝试根据请求参数选择openId授权方案。
我添加了两个 openIdConnect 模式:
.AddOpenIdConnect("abc", abcHandler)
.AddOpenIdConnect("def", defHandler);
一开始我覆盖了整个授权中间件并挑战:
if (authorizeResult.Challenged)
{
if (valueFromQueryString.Contains("abc"))
{
await context.ChallengeAsync("abc");
}
else if (valueFromQueryString.Contains("def"))
{
await context.ChallengeAsync("def");
}
}
但后来我注意到有一些政策,所以尝试使用这些政策。我创建了我的要求,然后添加了两个具有如下模式的策略:
services.AddAuthorization(options =>
{
options.AddPolicy("abc", policy =>
{
policy.AuthenticationSchemes.Add("abc");
policy.Requirements.Add(new TenantSpecificRequirement("abc"));
policy.RequireAuthenticatedUser();
});
options.AddPolicy("def", policy =>
{
policy.AuthenticationSchemes.Add("def");
policy.Requirements.Add(new TenantSpecificRequirement("def"));
policy.RequireAuthenticatedUser();
});
});
我意识到策略必须像这样绑定到控制器:
[Authorize(Policy = "abc")]
[Authorize(Policy = "def")]
这完全不是我需要的。现在最好的办法是根据 url 将策略动态分配给控制器,但似乎不可能,因为应用程序启动时不会添加控制器过滤器。
那还有没有别的办法呢?
好的,我通过覆盖 AuthenticationSchemeProvider
找到了解决方案
public class SubdomainAuthenticationSchemeProvider : AuthenticationSchemeProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CustomAuthenticationSchemeProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<AuthenticationOptions> options)
: base(options)
{
this._httpContextAccessor = httpContextAccessor;
}
private Task<AuthenticationScheme> GetRequestSchemeAsync()
{
// Get the subdomain for the host the request came from. Assumes no WWW in the string.
var subdomainName = _httpContextAccessor.HttpContext.Request.Host.Host.Split(new char[] { '.' })[0];
return GetSchemeAsync(subdomainName);
}
public override async Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() => await GetRequestSchemeAsync() ;
public override async Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultChallengeSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultForbidSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignInSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignInSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignOutSchemeAsync();
}
在此之后,将其添加到 ConfigureServices 方法中
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthenticationSchemeProvider, SubdomainAuthenticationSchemeProvider>();
我正在尝试根据请求参数选择openId授权方案。
我添加了两个 openIdConnect 模式:
.AddOpenIdConnect("abc", abcHandler)
.AddOpenIdConnect("def", defHandler);
一开始我覆盖了整个授权中间件并挑战:
if (authorizeResult.Challenged)
{
if (valueFromQueryString.Contains("abc"))
{
await context.ChallengeAsync("abc");
}
else if (valueFromQueryString.Contains("def"))
{
await context.ChallengeAsync("def");
}
}
但后来我注意到有一些政策,所以尝试使用这些政策。我创建了我的要求,然后添加了两个具有如下模式的策略:
services.AddAuthorization(options =>
{
options.AddPolicy("abc", policy =>
{
policy.AuthenticationSchemes.Add("abc");
policy.Requirements.Add(new TenantSpecificRequirement("abc"));
policy.RequireAuthenticatedUser();
});
options.AddPolicy("def", policy =>
{
policy.AuthenticationSchemes.Add("def");
policy.Requirements.Add(new TenantSpecificRequirement("def"));
policy.RequireAuthenticatedUser();
});
});
我意识到策略必须像这样绑定到控制器:
[Authorize(Policy = "abc")]
[Authorize(Policy = "def")]
这完全不是我需要的。现在最好的办法是根据 url 将策略动态分配给控制器,但似乎不可能,因为应用程序启动时不会添加控制器过滤器。
那还有没有别的办法呢?
好的,我通过覆盖 AuthenticationSchemeProvider
public class SubdomainAuthenticationSchemeProvider : AuthenticationSchemeProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CustomAuthenticationSchemeProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<AuthenticationOptions> options)
: base(options)
{
this._httpContextAccessor = httpContextAccessor;
}
private Task<AuthenticationScheme> GetRequestSchemeAsync()
{
// Get the subdomain for the host the request came from. Assumes no WWW in the string.
var subdomainName = _httpContextAccessor.HttpContext.Request.Host.Host.Split(new char[] { '.' })[0];
return GetSchemeAsync(subdomainName);
}
public override async Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() => await GetRequestSchemeAsync() ;
public override async Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultChallengeSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultForbidSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignInSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignInSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignOutSchemeAsync();
}
在此之后,将其添加到 ConfigureServices 方法中
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthenticationSchemeProvider, SubdomainAuthenticationSchemeProvider>();