以下に定義するカスタムポリシーベースの承認ハンドラーがあります。ユーザーがこのアプリケーションにアクセスする前に認証が処理されるため、承認のみが必要です。エラーが発生します:
AuthenticationSchemeが指定されておらず、DefaultForbidSchemeがありませんでした。
承認チェックが成功した場合、エラーは発生せず、すべて順調です。このエラーは、許可検査が失敗した場合にのみ発生します。失敗すると401が返されると思います。
public class EasRequirement : IAuthorizationRequirement
{
public EasRequirement(string easBaseAddress, string applicationName, bool bypassAuthorization)
{
_client = GetConfiguredClient(easBaseAddress);
_applicationName = applicationName;
_bypassAuthorization = bypassAuthorization;
}
public async Task<bool> IsAuthorized(ActionContext actionContext)
{
...
}
}
public class EasHandler : AuthorizationHandler<EasRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EasRequirement requirement)
{
var mvcContext = context.Resource as ActionContext;
bool isAuthorized;
try
{
isAuthorized = requirement.IsAuthorized(mvcContext).Result;
}
catch (Exception)
{
// TODO: log the error?
isAuthorized = false;
}
if (isAuthorized)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
context.Fail();
return Task.FromResult(0);
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var easBaseAddress = Configuration.GetSection("EasBaseAddress").Value;
var applicationName = Configuration.GetSection("ApplicationName").Value;
var bypassAuthorization = bool.Parse(Configuration.GetSection("BypassEasAuthorization").Value);
var policy = new AuthorizationPolicyBuilder()
.AddRequirements(new EasRequirement(easBaseAddress, applicationName, bypassAuthorization))
.Build();
services.AddAuthorization(options =>
{
options.AddPolicy("EAS", policy);
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton<IAuthorizationHandler, EasHandler>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
}
承認と認証はASP.NET Coreで密接にリンクされています。承認が失敗すると、これは認証ハンドラに渡されて承認の失敗を処理します。
したがって、ユーザーを識別するために実際の認証が必要ない場合でも、禁止およびチャレンジの結果を処理できる認証スキームを設定する必要があります(403および401)。
そのためには、AddAuthentication()
を呼び出して、デフォルトの禁止/チャレンジスキームを構成する必要があります。
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = "scheme name";
// you can also skip this to make the challenge scheme handle the forbid as well
options.DefaultForbidScheme = "scheme name";
// of course you also need to register that scheme, e.g. using
options.AddScheme<MySchemeHandler>("scheme name", "scheme display name");
});
MySchemeHandler
はIAuthenticationHandler
を実装する必要があり、あなたの場合、特にChallengeAsync
とForbidAsync
を実装する必要があります:
public class MySchemeHandler : IAuthenticationHandler
{
private HttpContext _context;
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
_context = context;
return Task.CompletedTask;
}
public Task<AuthenticateResult> AuthenticateAsync()
=> Task.FromResult(AuthenticateResult.NoResult());
public Task ChallengeAsync(AuthenticationProperties properties)
{
// do something
}
public Task ForbidAsync(AuthenticationProperties properties)
{
// do something
}
}
IIS/IIS Expressの場合、承認された回答に上記のすべての代わりにこの行を追加するだけで、期待する適切な403応答を取得できます。
services.AddAuthentication(IISDefaults.AuthenticationScheme);