先日 ASP.NET Core で Basic 認証を行うサンプルを書いた。
ただ、これだと全てのパスで認証が必要になってしまう。 もともとやりたかったことは、 「ASP.NET Core MVC で Authorized 属性を付けたアクションだけを認証必須にすること」。
Microsoft.AspNetCore.Authentication をベースに Basic 認証ミドルウェアを作れば実現できそうだったけど、既に同じことをやっている人がいた。
NuGet でパッケージが公開されているので、使わせてもらうことにした。
using idunno.Authentication; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System.IO; using System.Security.Claims; using System.Threading.Tasks; namespace BasicAuthExample { public class Program { public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .UseApplicationInsights() .Build(); host.Run(); } } public class Startup { public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfigurationRoot Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); // Basic 認証を使用する app.UseBasicAuthentication(new BasicAuthenticationOptions() { Realm = "BasicAuthExample", Events = new BasicAuthenticationEvents() { OnValidateCredentials = context => { // ユーザー名とパスワードはとりあえず固定 if (context.Username == "tnakamura" && context.Password == "test12345") { var claims = new Claim[] { new Claim(ClaimTypes.Name, context.Username), }; var identity = new ClaimsIdentity(claims, context.Options.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); context.Ticket = new AuthenticationTicket( principal, new AuthenticationProperties(), context.Options.AuthenticationScheme); } return Task.FromResult(true); }, } }); app.UseMvcWithDefaultRoute(); } } public class HomeController : Controller { [HttpGet("/")] public string Index() { return "Hello World!"; } // アクセスすると認証ダイアログが表示される [Authorize] [HttpGet("/hello")] public string Hello() { return $"Hello {User.Identity.Name}!"; } } }
これで、Authorize 属性が付いたアクションの呼び出しに Basic 認証が効くようになった。 今回もユーザー名とパスワードは固定なので、ここはデータベースから取得した方が良いだろう。
OnValidateCredentials に登録するデリゲートでは、context.HttpContext.RequestServices
を使って DI コンテナに登録した DbContext や自作リポジトリなんかを取得できるので、実装するのは難しくないはず。