動的データ Web サイトでロールを設定しようとしていますが、問題が発生しています。
ジェネリック プリンシパルで設定してから、既定のページにアクセスすると、プリンシパルの役割が失われます。プリンシパルは引き続き context.user としてリストされます。これは、セッションをデバッグして context.user オブジェクトを検査するときに、設定したユーザーが設定したユーザーであるためです。しかし、そのユーザーに関連するすべての役割が失われたようです。
これが私がそれについて行っている方法です。
ログインページ
public partial class Login : System.Web.UI.Page
{
string[] masterServiceResult;
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (IsAuthenticUser(login_email.Text, login_password.Text))
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, masterServiceResult[0], DateTime.Now, DateTime.Now.AddMinutes(30), false, masterServiceResult[2], FormsAuthentication.FormsCookiePath);
string encryptedCookie = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookie);
Response.Cookies.Add(cookie);
Response.Redirect(FormsAuthentication.GetRedirectUrl(masterServiceResult[0], true));
}
}
private bool IsAuthenticUser(string email, string password)
{
MembershipService membershipService = new MembershipService();
var result = membershipService.GetUserAndRoleFromCredentials(email, password);
//result is an array with userName, userId, error(bool) as string, and error message if any
if (bool.Parse(result[3]) == false)
{
masterServiceResult = result;
return true;
}
return false;
}
}
次に、Global.asax で AuthenticateRequest イベントにアタッチしました
void Global_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
SetupRoles();
}
private void SetupRoles()
{
if (Context.User != null)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (authCookie == null)
return;
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(new char[] { '|' });
IIdentity fi = Context.User.Identity;
IPrincipal pi = new GenericPrincipal(fi, roles);
Context.User = pi;
//sets the application principal to use the logged on user account
System.Threading.Thread.CurrentPrincipal = System.Web.HttpContext.Current.User;
// sanity check to ensure the role was set up.
if (User.IsInRole("Admin"))
{
int i = 0; // debug line
}
}
}
この時点で、すべてが意図したとおりに機能しています。テスト アカウントが context.user として設定され、現在のプリンシパル ユーザーが現在のユーザーとして設定され、管理者のユーザー ロールが原因で "int i=0" デバッグ行がヒットします。ただし、デフォルト ページの Page_Load がヒットすると、これはもはや当てはまりません。
デフォルトのページ。別のテスト ケースを示すために 01/03/12 を更新。protected void Page_Load(object sender, EventArgs e) { System.Collections.IList visibleTables = MetaModel.Default.VisibleTables;
// this line comes back as false, though at this point the user name is the same.
if (User.IsInRole("Admin"))
{
int i = 0;
}
// the next 4 lines of code is a work around I can do to retrieve the roles from the ticket.
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
// this line of code will correctly show the users role
string[] roles = authTicket.UserData.Split(new char[] { '|' });
foreach (var table in MetaModel.Default.Tables)
{
var permissions = ((MetaTable)table).GetTablePermissions(roles);
if (permissions.Contains(TablePermissionsAttribute.Permissions.DenyRead))
visibleTables.Remove(table);
}
if (visibleTables.Count == 0)
{
throw new InvalidOperationException("There are no accessible tables. Make sure that at least one data model is registered in Global.asax and scaffolding is enabled or implement custom pages.");
}
Menu1.DataSource = visibleTables;
Menu1.DataBind();
}
*更新: 認証チケットからユーザーのロールを取得でき、プリンシパルは正しいのですが、User.IsInRole 行が失敗する理由がわかりません。