ASP.NET Identity プロファイルの追加
この記事は One ASP.NET Advent Calendar 2013 の10日目の記事です。
デフォルトのテンプレートを利用している場合、ASP.NET Identity ではユーザーの情報として独自のデータ保持できるようにデータベースを拡張することが Entity Framework の Migration の機能を利用することで比較的簡単にできるようになっています。
どのような手順が必要か、は以下の記事で十分わかるかと。
Customizing profile information in ASP.NET Identity in VS 2013 templates
ということで、これで今回の記事は終わり、、、ではあまりに悲しいので、上記記事では ASP.NET MVC でやっているところを WebForms を使っても同じことができることを検証してみます。
サンプルアプリケーションとしては、以前の記事でつくったものにユーザーの表示名( DisplayName )を追加し、ログイン時の表示をユーザー名から表示名に変えてみることにします。
まず、 ApplicationUser クラスに DisplayName プロパティを追加します。
この状態で一度ビルドを実行しておいて、ここからは Entity Framework のマイグレーションの手順を実行します。
メニューから「ツール」-「ライブラリ パッケージ マネージャー」-「パッケージ マネージャー コンソール」とたどって、パッケージマネージャーコンソールを表示させます。
そこで
- Enamble-Migrations
- Add-Migration "DisplayName" <- 文字列は作成されるファイル/クラス名に使われるので他と区別できればなんでもよい
- Update-Database
と実行します。
えと、上記キャプチャで実行順まちがえてエラーになっているのはスルーの方向で(w
この操作により、 Migrations フォルダが作成され、DBの構成変更に必要なプログラムが自動生成されます。
また、実際に作成ずみの DB に DisplayName 項目が追加されます。
あとはこれを使っていくだけですね。
Register.aspx (ユーザー登録画面)に表示名の入力欄を追加します。
また、Register.aspx.cs ファイルに DisplayName を保存するプログラムを追記します。
とりあえず、DisplayName の登録についてはこれだけでOK。
表示のほうですが、 Site.Master.cs ファイルに DisplayName を取得する GetDisplayNmae() メソッドを以下のように追加します。
一度 UserManager オブジェクトを生成して、そこから UserID をキーに ApplicationUser オブジェクトをとりだし、 DisplayName を取得する、という手順を踏む必要があります。
また、 using で必要な名前空間を指定しておく必要があります。
この名前空間が正しく指定されていないと、たとえば Context.User.Identity オブジェクトは存在するのに GetUserId() メソッドが存在しない(ようにみえる)なんてことがあるので注意です。
で、このメソッドの追加ができたら、 Site.Master.aspx ファイルのユーザー名の表示箇所をこのメソッドに置き換えましょう。
さて、これで実行してみます。
こんな感じで登録すると
登録に成功するときちんと表示名が表示されるようになります。
以前もユーザーのプロファイルを保持する仕組みというのは存在していたんですが、使いにくいところがありました。
これならデータベースの構造もわかりやすいですね。
UserId をもとにログインしているユーザーのプロパティを取得する方法はこれでいいんですが。。。
管理者がすべてのユーザーの情報を表示したい、なんてときはどうするのがよいのか、今悩んでます。
直接 DB から取り出して利用するしかないのかなぁ。。。
このあたりはまだ宿題、ということで。
ASP.NET Identity を読み解く
前回の記事で ASP.NET Identity でなにができるのか、はざっくり説明しました。
で、これがどのように実現されているのか、を調べてみました。
まずは Web.config になにか情報がないか、もう一度確認してみると。。。
認証の設定モードを None にしているだけでなく、認証に利用する FormsAuthenticationModule をはずしています。
これ以上の情報は Web.config 内にはないようです。
では、ソースコードになにか情報はないか。
Startup.Auth.cs で UseCookieAuthentication メソッドを呼び出しています。
このメソッドは何をやっているんでしょう。。。
ということでいろいろ情報をさがしていくと、 Katana プロジェクトというものにいきつきました。
Katana プロジェクトの概要
このプロジェクトについては上記 MSDN マガジンの記事でみていただくとして。
Katana プロジェクトは Codeplex 上に展開されていますので、ここからソースコードを取り出すことができます。
http://katanaproject.codeplex.com/
テンプレートで利用されているすべてのモジュールのソースコードが存在するわけではありませんが、 UseCookieAuthentication メソッドについては CookieAuthenticationExtensions クラスのメソッドとしてソースを参照することができます。
で、 UseCookieAuthentication メソッドの内容は、ほぼこの2行。
app.Use(typeof(CookieAuthenticationMiddleware), app, options);
app.UseStageMarker(PipelineStage.Authenticate);
1行めは CookieAuthenticationMiddleware を利用するために登録している、といったところでしょうか。
で、2行めは HttpApplication の AuthenticateRequest イベントのタイミングで CookieAuthenticationMiddleware を利用することで登録される CookieAuthenticationHandler を実行する、ということになるのかな?
2行めの UseSategeMarker メソッドについては次の Blog の記事が参考になります。
OWIN Middleware in the IIS integrated pipeline
CookieAuthenticationHandler では認証チケット(cookie)を解析して、問題がなければ AuthenticationTicket を生成し、その内容が最終的には HttpContext 内の User オブジェクトに設定されるようです。
WebForms や ASP.NET MVC の承認の機能はこの User オブジェクトの中身をみて認証済みかどうか、といった判断をしているので、こちらは以前のまま、ということになるようです。
Startup.Auth.cs には UseGoogleAuthentication 他のメソッドがありますが、これらも大きな動きは同じようになっていると思われます。
ただ、 UseGoogleAuthentication の場合、
app.UseStageMarker(PipelineStage.Authenticate);
この UseStageMarker の設定が存在しないので、認証のタイミングはデフォルトの PreRequestHandlerExecute イベントのときになるのかな?
ASP.NET Identity をひととおり使う分にはこんなとこまで知ってる必要は「まったく」ないですが、ついつい調べちゃうのはプログラマの性ですかね(^^;
さて、疑問におもってたところがなんとなくは理解できたので、次は自分の要求にあったカスタマイズをどう実現していくか、という方向に走りますか。。。