こんにちは。
テックリードのTerukiです。
ASP.NET Core Identityという、公式の認証関連のライブラリがあります。
EF Coreと一緒に使う想定なら非常にスムーズに基本的な機能を実装できるのでかなり良いです。
そんな多機能なライブラリですが、各ユーザーの最終ログイン日時を記録することがデフォルトの機能ではできないので、今回はそれをやってみます。
前提
ASP.NET Core自体、大抵のデフォルト実装をDI経由で差し替えられるような設計になっているので、今回は基本的であることを前提に実装してみます。
既に諸々カスタマイズされているような環境でも、実装のヒントにはなるかなと思うので良ければ見てもらえたらと。
方針
上述の通り大抵の実装を差し替えれば理論上はなんでもできるわけですが、それでは実装量がとんでもないことになるので基本は既にあるやつをうまいこと使います。
サインイン完了処理にフックできれば実現できそうですが、SignInManagerをオーバーライドしてSignInAsyncをフックするみたいなのはちょっとカロリーが高そうです。
通常認証完了時にはそのセッション情報をCookieに保存するので、CookieAuthenticationEventsというイベントたちを活用できそうです。
サインイン完了直後に呼ばれるOnSignedInに処理を追加すれば実現できそうです。
実装
まず準備です。ASP.NET Core IdentityにあるUserテーブルをオーバーライドして最終ログイン日時のカラムを追加しておきます。
public class ApplicationUser : IdentityUser {
/// <summary>
/// 最終ログイン日時
/// </summary>
public DateTimeOffset? LastLoggedInAt { get; set; }
}
DIに登録します。
services.AddIdentityApiEndpoints<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
OnSignedInをフックして LastLoggedInAt
を更新するようにします。
services.ConfigureApplicationCookie(options => {
options.Events.OnSignedIn = async context => {
var dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();
var timeProvider = context.HttpContext.RequestServices.GetRequiredService<TimeProvider>();
var user = await userManager.GetUserAsync(context.Principal!).ConfigureAwait(false);
// 最終ログイン日時の保存
await dbContext.Users.Where(u => u.Id == user.Id)
.ExecuteUpdateAsync(u => u.SetProperty(s => s.LastLoggedInAt, timeProvider.GetUtcNow()))
.ConfigureAwait(false);
};
});
今回はDbContextのTrackingが絡むとややこしくなるので、Change Tracker経由ではなくExecuteUpdate
を使って更新しています。
これ便利ですよね。
これで最終ログイン時のDB保存ができました。
社内システム開発において、これあると良いよねということで調べ始めたのですが調べても意外と情報が出てこなかったのでこの際記事にしてみました。
あんまり需要があるかは不明ですが誰かの役に立てば良いなと。
Oh my teethについて
Oh my teethでは未来の歯科体験を創るために日々活動しています。
Techチームではより良いユーザー体験を提供するべく、Webフロントエンドからバックエンド、スマホアプリに機械学習モデルなど、さまざまなプロダクトを開発しています。
一緒に未来の歯科体験を創りませんか?興味がある方は是非こちらを確認してください。
カジュアル面談も可能なので気軽に応募してみてください!
