先日 ASP.NET Core で Basic 認証を行うサンプルを書いた。
tnakamura.hatenablog.com
ただ、これだと全てのパスで認証が必要になってしまう。
もともとやりたかったことは、
「ASP.NET Core MVC で Authorized 属性を付けたアクションだけを認証必須にすること」。
Microsoft.AspNetCore.Authentication をベースに Basic 認証ミドルウェアを作れば実現できそうだったけど、既に同じことをやっている人がいた。
github.com
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();
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 や自作リポジトリなんかを取得できるので、実装するのは難しくないはず。