ASP.NETユーザ管理(ASP.NET Identityフレームワーク)の6回目です。前回は、メンバー専用エリアと管理者ページの各制限方法を確認しました。今回はロール管理を使ってみます。前回では、Web.configでユーザ単位の制限を設定しました。ユーザも数が少なければこのようにユーザ単位で管理をすればいいですが数が増えるとロール(グループ)単位の管理の方が効率が良くなってくると思います。ということでロールの管理の方法を確認します。
今回のソース一式はこちらです。今回の部分は(ISY04)ではじまるコメントを付けています。(※ユーザ登録時のメール送信処理も含まれています。必要な場合はお手数ですが、こちらを参照してメール送信のアカウントを設定するか、メール送信処理を削除して下さい。)
ロール関連のクラス
ASP.NETユーザ管理(その2)WebFormsでのASP.NET Identityでも書きましたが、主なロール関連のクラスは以下です。
Microsoft.AspNet.Identity.RoleManagerクラス
ロールとユーザの関連付け等、一連のロール管理クラス
Microsoft.AspNet.Identity.EntityFramework.IdentityRole
既定の EntityFramework IRole 実装でロールのエンティティ
ロール管理の実装
上記のロール関連のクラスをどのように利用するかは設計次第です。通常、WebFormsのテンプレートでは、ApplicationUserManagerクラスを利用してユーザの管理を行います。そうすると、ApplicationRoleManagerクラスといった名称で新規クラスを作成するのが普通の設計方法だとは思いますが、ここではApplicationUserManagerクラスにロール関連の処理も含めてしまいます。この方法の場合、WebFormのビハインドコードで、ApplicationUserManagerのみを決まった方法で取得すればユーザ管理、ロール管理全て利用出来るので簡単かと思いました。この場合、せめてクラス名をApplicationUserRoleManager等に変更した方がいいかと思いますが、ここではそのままのクラス名にしておきます。
ApplicationUserManagerクラスの拡張
ApplicationUserManagerは、(ホーム)\App_Start\IdentityConfig.csに記述されています。ここに以下のロール管理の実装を追加しました。
/// <summary> /// ロールマネージャの追加 /// </summary> private RoleManager<IdentityRole> roleManager = new RoleManager<IdentityRole>( new RoleStore<IdentityRole>(new ApplicationDbContext())); /// <summary> /// Roleのリストを返す /// </summary> public List<IdentityRole> Roles { get { return roleManager.Roles.ToList(); } } /// <summary> /// Roleの名前での検索 /// </summary> /// <param name="Name"></param> /// <returns></returns> public IdentityRole RoleByName(string Name) { return roleManager.FindByName(Name); } /// <summary> /// 新規Roleの作成 /// </summary> /// <param name="name"></param> /// <param name="description"></param> /// <returns></returns> public bool CreateRole(string name, string description = "") { var role = this.RoleByName(name); if (role != null) { return false; } var idResult = roleManager.Create(new IdentityRole(name)); return idResult.Succeeded; }
RoleManagerをメンバー変数にして基本的な処理をメソッドにして公開します。これらをテストするためのWebformを以下のように用意しました。
通常、こういった処理は管理者のみが実行出来るようにしますが、テストのためここではその制限ははずしています。つまり、ログインしないでも、(ホーム)/Administrator/Default.aspxで表示します。以下の処理がテスト出来ます。
ユーザ管理
・ユーザの削除
ロール管理
・新規ロールの追加登録
・ロールにユーザを追加する
・ロールからユーザを除外する
Webformのソースは以下です。テスト用のシンプルなページです。
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ASPNETWebFormsIdentity.Administrator.Default" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h1>管理者ページ</h1> <h3>ユーザ・ロール管理</h3> <hr /> <b>ユーザ管理</b> <p>全ユーザ一覧</p> <p> <asp:DropDownList ID="ddlUser" runat="server"> </asp:DropDownList> <asp:Button ID="btnToTarget" runat="server" Text="ロール処理対象ユーザへコピー" OnClick="btnToTarget_Click" Width="250px" /> </p> <p><asp:Button ID="btnUserDel" runat="server" Text="選択されているユーザを削除する" OnClick="btnUserDel_Click" Width="260px" /></p> <hr /> <b>ロール管理</b> <p>全ロール一覧</p> <p> <asp:DropDownList ID="ddlRole" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ddlRole_SelectedIndexChanged"> </asp:DropDownList> </p> <p> <asp:TextBox ID="txtNewRole" runat="server"></asp:TextBox> <asp:Button ID="btnNewRole" runat="server" Text="新規ロール追加登録" OnClick="btnNewRole_Click" /> </p> <p>選択ロールユーザ一覧</p> <p> <asp:ListBox ID="lstRoleUser" runat="server"></asp:ListBox> </p> <p>ロール処理対象ユーザ</p> <p> <asp:TextBox ID="txtTargetUser" runat="server" Width="250px"></asp:TextBox> </p> <p><asp:Button ID="btnAddRole" runat="server" Text="対象ユーザを選択されているロールに追加する" OnClick="btnAddRole_Click" Width="320px" /></p> <p><asp:Button ID="btnDelRole" runat="server" Text="対象ユーザを選択されているロールから除外する" OnClick="btnDelRole_Click" Width="320px" /></p> </asp:Content>
ビハインドコードは以下です。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Microsoft.AspNet.Identity.EntityFramework; using Owin; using ASPNETWebFormsIdentity.Models; namespace ASPNETWebFormsIdentity.Administrator { public partial class Default : System.Web.UI.Page { /// <summary> /// ページの読み込み時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load(object sender, EventArgs e) { //PostBack時以外 if (!IsPostBack) { var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); ddlRole.Items.Clear(); ddlUser.Items.Clear(); foreach (var user in manager.Users) { ddlUser.Items.Add(new ListItem(user.UserName, user.UserName)); } foreach (var role in manager.Roles) { ddlRole.Items.Add(new ListItem(role.Name, role.Name)); } ddlRole.SelectedIndex = 0; dispSelRoleUser(); } } /// <summary> /// ロールの追加 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnAddRole_Click(object sender, EventArgs e) { if (txtTargetUser.Text.Length == 0) { return; } var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); string selRole = ddlRole.SelectedValue; ApplicationUser user = manager.FindByName(txtTargetUser.Text); manager.AddToRole(user.Id, selRole); dispSelRoleUser(); } /// <summary> /// 選択されたロールのユーザ一覧を表示 /// </summary> private void dispSelRoleUser() { string selRole = ddlRole.SelectedValue; if (selRole.Length == 0) { return; } var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); IdentityRole role = manager.RoleByName(selRole); lstRoleUser.Items.Clear(); if (role.Users == null) { return; } foreach (var roleUser in role.Users) { string userName = manager.FindById(roleUser.UserId).UserName; lstRoleUser.Items.Add(new ListItem(userName, userName)); } } /// <summary> /// ロール選択変更時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void ddlRole_SelectedIndexChanged(object sender, EventArgs e) { dispSelRoleUser(); } /// <summary> /// ユーザの選択 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnToTarget_Click(object sender, EventArgs e) { string selUser = ddlUser.SelectedValue; txtTargetUser.Text = selUser; } /// <summary> /// ユーザ削除 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnUserDel_Click(object sender, EventArgs e) { var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); string selUser = ddlUser.SelectedValue; ApplicationUser user = manager.FindByName(selUser); manager.Delete(user); ddlUser.Items.Clear(); foreach (var userItem in manager.Users) { ddlUser.Items.Add(new ListItem(userItem.UserName, userItem.UserName)); } dispSelRoleUser(); } /// <summary> /// ユーザ削除 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnDelRole_Click(object sender, EventArgs e) { if (txtTargetUser.Text.Length == 0) { return; } var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); string selRole = ddlRole.SelectedValue; ApplicationUser user = manager.FindByName(txtTargetUser.Text); manager.RemoveFromRole(user.Id, selRole); dispSelRoleUser(); } /// <summary> /// 新規ロール追加 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnNewRole_Click(object sender, EventArgs e) { var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); manager.CreateRole(txtNewRole.Text); ddlRole.Items.Clear(); foreach (var role in manager.Roles) { ddlRole.Items.Add(new ListItem(role.Name, role.Name)); } ddlRole.SelectedIndex = 0; dispSelRoleUser(); } } }
ロールでのアクセス制限ですが、前回の、ユーザでの制限のようにWeb.configで制限をかけられます。 Web.confi内の記述で、allow roles=”Administrator”といった記述で制限可能です。今回はここまでです。次回は、ユーザアカウントロックについてです。
今回のシリーズの一覧
ASP.NETユーザ管理(その1)identityフレームワーク
ASP.NETユーザ管理(その2)WebFormsでのASP.NET Identity
ASP.NETユーザ管理(その3)ユーザ登録時のメール確認
ASP.NETユーザ管理(その4)ユーザ情報の追加
ASP.NETユーザ管理(その5)メンバー専用エリアと管理者ページ
ASP.NETユーザ管理(その6)ロール管理の追加
ASP.NETユーザ管理(その7)ユーザアカウントロック
ASP.NETユーザ管理(その8) 2要素認証
ASP.NETユーザ管理(その9) パスワードのリセット