2

久しぶりのラーカー初めてのポスター..

MVC の単純なカスタム ロールとメンバーシップ プロバイダーを実装しようとしています。

ロールとメンバーシップ プロバイダー クラスを実装し、web.config にフックしました。カスタムデータベースに対してユーザーを検証するコードを追加しましたが、正常に動作します。

ただし、ロールプロバイダーがリクエストごとにデータベースにヒットする方法が気に入らないため、次のように認証チケットからこれを読み取ろうとするコードを追加しました。

カスタム ロール プロバイダー:

public override string[] GetRolesForUser(string username)
   {
       if (HttpContext.Current.User != null)
       {
           return ((UserPrincipal)HttpContext.Current.User).Roles.ToArray();
       }
       else
       {
           UserPrincipal user = orchestrator.GetUserByLoginID(username);
           return user.Roles.ToArray();
       }
   }

次に、次のコードを global.asax に追加して、カスタム ユーザー プリンシパル オブジェクトを使用して、役割やその他の有用なユーザー情報を Cookie に保持します。

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
    {
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

        if (authCookie != null)
        {
            FormsAuthenticationTicket authTicket =      FormsAuthentication.Decrypt(authCookie.Value);

            JavaScriptSerializer serializer = new JavaScriptSerializer();

            UserPrincipalModel userFromTicket = serializer.Deserialize<UserPrincipalModel>(authTicket.UserData);

            UserPrincipal newUser = new UserPrincipal();
            newUser.UserId = userFromTicket.UserId;
            newUser.FullName = userFromTicket.Fullname;
            newUser.Email = userFromTicket.Email;
            newUser.Roles = userFromTicket.Roles;
            newUser.Identity = new GenericIdentity(userFromTicket.Username);

            HttpContext.Current.User = newUser;
        }
    }

私のユーザープリンシパルクラス:

  public class UserPrincipal : IPrincipal
{
    public UserPrincipal() { }
    public UserPrincipal(int userId, string userName, string fullName, string password)
    {
        UserId = userId;
        UserName = userName;
        FullName = fullName;
        Password = password;
    }
    public virtual int UserId { get; set; }
    public virtual string UserName { get; set; }
    public virtual string FullName { get; set; }
    public virtual string Email { get; set; }
    public virtual string Password { get; set; }        
    public virtual IEnumerable<string> Roles { get; set; }

    public virtual IIdentity Identity { get; set; }

    public virtual bool IsInRole(string role)
    {
        if (Roles.Contains(role))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

   //public string[] GetRolesForUser()
   //{
   //    return Roles;
   //}
}

ただし、これを実行すると、ロール プロバイダーが Cookie のカスタム UserPrincipal オブジェクトにアクセスしようとすると、次のエラーが発生します。

「タイプ 'System.Web.Security.RolePrincipal' のオブジェクトをタイプ 'MyApp.Domain.UserPrincipal' にキャストできません」

カスタム ロール プロバイダーが、チケットに格納されているカスタム ユーザー プリンシパルを独自のロール固有のプリンシパルで上書きしているようなものです。

私がやろうとしていることに欠陥があるのか​​ 、それとももっと簡単な方法があるのか​​ 疑問に思っています。車輪を再発明したくありません。

ロールのリクエストごとにデータベースにアクセスしないカスタム ロール プロバイダーの例を知っている人はいますか?

4

1 に答える 1

1

ここでこれを変更します。

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 

ここまで:

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)

基本的に、デフォルトのロール プロバイダーの内部動作は、設定後に HttpContext.Current.User プロパティを設定するため、行ったことを上書きします。

デフォルトのロール プロバイダーを試してクリアすることもできます。mvc3 および asp.net Web フォームでは機能するようですが、mvc 4 では失敗します。

<membership>
  <providers>
    <clear />
  </providers>
</membership>
<profile>
  <providers>
    <clear />
  </providers>
</profile>
<roleManager enabled="false">
  <providers>
    <clear />
  </providers>
</roleManager>
于 2012-11-13T21:49:03.650 に答える