WebMatrix でユーザー認証機能(5) ―― ロール
- WebMatrix でユーザー認証機能 ―― 準備編 - だるろぐ
- WebMatrix でユーザー認証機能(2) ―― WebSecurityってどうやって使うんだ? - だるろぐ
- WebMatrix でユーザー認証機能(3) ―― なにはともあれユーザー登録しないと始まらん - だるろぐ
- WebMatrix でユーザー認証機能(4) ―― ログインとログオフ - だるろぐ
とりあえずログイン機能があらかた実装できたけれど、これだとだれでもユーザーが作れてしまう。まぁ、そういうアプリもあるけど、“管理者”のみがユーザーを作成できるほうが望ましいこともある。そういった“管理者”権限を実現したいときにはどうするかというと、“ロール(Roles)”を使うんだな。
System.Web.Security.Roles
ロールの作成方法については、ここらあたり(Adding Security and Membership to an ASP.NET Web Pages (Razor) Site | Microsoft Docs)が詳しい。
その例だとロールの作成するためにデータベースを直接イジっていて、一瞬「あちゃー、コードでやろうと思ったら SQL 書かなきゃいけないのかな?」と思ってしまったけど、ちゃんと Roles を扱うクラスが用意されていた*1。
http://msdn.microsoft.com/en-us/library/system.web.security.roles.aspx
とりあえずさらっと目を通しておくとよさげ。
Roles.RoleExists() / Roles.CreateRole()
まず、 _AppStart.cshtml で“ロールがなければ作成する”という処理を追加してみた。
@{ App.DATABASE = "database"; // <-- カッコ悪いし、 App.TABLE_USERS = "Users"; // あとで静的クラスにまとめて App.ROLE_ADMIN = "admin"; // リードオンリーにしておくべき WebSecurity.InitializeDatabaseConnection( App.DATABASE, App.TABLE_USERS, "UserId", "Name", true); if (!Roles.RoleExists(App.ROLE_ADMIN)) // <-- ココ! { Roles.CreateRole(App.ROLE_ADMIN); } }
できたっぽい。拍子抜けしたぞなもし。
Roles.AddUserToRole()
つぎに、“初めて登録されたユーザーは管理者にする”ということにしてみようか。
# ~/Account/Register.cshtml try { WebSecurity.CreateUserAndAccount( name, password, new { Name = name }); WebSecurity.Login(name, password); // 最初のユーザーには管理者権限を付与 if (App.GetUserCount() <= 1) { Roles.AddUserToRole(name, App.ROLE_ADMIN); } Response.Redirect("~/"); } catch (Exception e) { ModelState.AddFormError(e.Message); }
ちゃんと UserId 1 に RoleId 1(admin)が紐付けられた。ちなみに、複数のユーザーを一度にロールへ突っ込むためのメソッドもある。
ちなみに、残念ながらユーザーの数を数えるメソッドは用意されていないみたいなので、これは SQL で書かないといけない。
@{ App.GetUserCount = (Func<int>)GetUserCount; // <-- 個人的趣味 } @functions { int GetUserCount() { const string sql = "SELECT COUNT(*) FROM {0}"; return Database .Open(App.DATABASE) .QueryValue(string.Format(sql, App.TABLE_USERS)); } }
でも、もしかしたらメソッドが用意されていない≒あんまりよくない実装 なのかもしれない。よく利用する処理なら、標準でメソッドが用意されているよね?*2 まぁ、それはまた今度考えよう。
Roles.IsUserInRole() / WebSecurity.RequireRoles()
んで、ロールが必要な処理には一行このように書き加えておく。この場合は、 Register.cshtml だね。 _PageStart.cshtml に書けば、フォルダ内の cshtml すべてに適用することもできる(はず、確かそうだった)。
@{ WebSecurity.RequireRoles(App.ROLE_ADMIN); }
必要なロールをもたなければ、ログインページにリダイレクトされる*3ようだ*4。
@{
if (!Roles.IsUserInRole(App.ROLE_ADMIN))
{
:
:
もちろん、ロールをもつかどうかの判定のみを行うこともできる。 寄り道: Rails の Flash っぽい機能を WebMatrix で使いたい - だるろぐ などを使ってユーザーにメッセージを通知したい場合など、いきなりリダイレクトされると困る場合はこっちを使ったほうがよさげだな。