2011-08-12 6 views
9

私はいくつかの追加フィールド(ユーザー名に加えて電子メールとユーザーID)を含むカスタムプリンシパルオブジェクトを作成しました。ASP.NET MVCでカスタムIPrincipalに簡単にアクセスできるようにするにはどうすればよいですか?

これらのプロパティにアクセスするには、私のカスタムプリンシパルとしてContext.Userオブジェクトをキャストする必要があります。

@Html.GetGravitarImage((User as CustomPrincipal).Email) 

このカスタムプリンシパルは、global.ascx内のApplication_AuthenticateRequestを使用して作成/逆シリアル化されます。あなたはこの質問を見ることができます。詳細はhereにお尋ねします。

ユーザーが認証されていない場合
private void Application_AuthenticateRequest(Object source, EventArgs e) 
{ 
    var application = (HttpApplication)source; 
    var context = application.Context; 

    // Get the authentication cookie 
    string cookieName = FormsAuthentication.FormsCookieName; 
    HttpCookie authCookie = context.Request.Cookies[cookieName]; 
    if (authCookie == null) 
     return; 

    var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
    context.User = CustomPrincipal.CreatePrincipalFromCookieData(authTicket.UserData); 
} 

しかし、その後、(それは上記の方法で注入されることはありませんので)CustomPrincipalに私のキャストが失敗し、(CustomPrincipalなどのユーザー)の結果がnullを返します。上記の方法でメールを取得しようとするとnull参照例外が発生します。

この問題を解決するにはどうすればよいですか?カスタムプリンシパルに簡単にアクセスできるようにしたいのですが、次のようにするのは面倒です。

@Html.GetGravitarIcon((User is CustomPrincipal) ? (User as CustomPrincipal).Email : "Default Email") 

これはこの状況を処理する唯一の方法ですか?

答えて

2

あなたは、基本クラスを作成し、このような拡張メソッドをキーワードまたは作成する「新しい」を使用して「ユーザー」プロパティをオーバーライドすることができ、次のいずれか

public static class ControllerExtensions 
{ 
    public static CustomPrincipal CustomPrincipal(this Controller controller) 
    { 
     if(controller.User is CustomPrincipal) 
     { 
      return controller.User as CustomPrincipal; 
     } 
     return null; // maybe return an empty object instead to get around null reference... 
    } 
} 
+0

それは私だけかもしれないが、私は拡張子を見つけます一般的な名前空間に定義されていない限り、一般的なことに迷惑をかける方法。 Ctrl-をクリックするだけではいけません。 Visual Studioで通常のように自動的にインクルードします。 –

+0

私は個人的に私はそれらを愛するが、それぞれ自分自身に私は推測する。これはSystem.Web.Mvc名前空間などに置くことができ、常に取得されます。 –

+0

私は現時点でこれについて私の頭を浮かそうとしており、私はMyUserClassが何であるか理解していません。説明していただけますか? – LukeP

0

あなたはユーティリティメソッドのいくつかの並べ替えを作成したり、追加することができますメソッドを使用してカスタムプリンシパルであるかどうかをチェックします。多分何かのように:

public class UserService : IUserService 
{ 
    public CustomPrincipal CurrentUser 
    { 
     get 
     { 
      CustomPrincipal user = HttpContext.Current.User as CustomPrincipal; 

      if (user == null) 
       return GuestUser; // Just some default user object 

      return user; 
     } 
    } 
} 
0

あなたはまた、ジョン・Kalbererの答えと同じように電子メールとユーザーIDのための拡張メソッドを作ることができる:

public static class CustomPrincipalExtensions 
{ 
    public static string Email(this CustomPrincipal cUser) 
    { 
     return cUser != null ? cUser.Email : "Default Email" 
    } 

    public static string UserID(this CustomPrincipal cUser) 
    { 
     return cUser != null ? cUser.UserID : "Default ID" 
    } 
} 
0

認可されていない場合は、あなたがユーザーオブジェクトを設定することができますデフォルトの値を持つカスタムプリンシパルの特定のインスタンス:

if (authCookie == null) 
{ 
    context.User = CustomPrincipal.Default; // Or CreateDefault() 
    return; 
} 
3

私は何かを素早くまとめました。

1)独自のIPrincipalをASP.NET MVCに簡単に導入する方法の1つは、1)IPrincipalインターフェイスの独自の子孫を作成します。

public interface IMyPrincipal : IPrincipal 
{ 
    Guid UserId { get; } 
    string EmailAddress { get; } 
} 

2)ASP.NETメンバーシッププロバイダを使用してユーザーを認証しているとします。メンバーシップAPIを利用するIMyPrincipalの実装をすぐに構築しましょう。

public class MyPrincipal : IMyPrincipal 
{ 
    private MembershipUser _user; 

    public MyPrincipal() 
    { 
     this._user = Membership.GetUser(); 
     var userName = this._user != null ? this._user.UserName : String.Empty; 
     this.Identity = new GenericIdentity(userName); 
    } 

    public Guid UserId 
    { 
     get 
     { 
      return this._user != null ? (Guid) this._user.ProviderUserKey : 
             default(Guid); 
     } 
    } 

    public string EmailAddress 
    { 
     get 
     { 
      return this._user != null ? this._user.Email : null; 
     } 
    } 

    public IIdentity Identity { get; private set; } 
    public bool IsInRole(string role) { return false; } 
} 

3)コントローラ用に独自の基本クラスタイプを作成します。継承されたUserメンバを非表示にし、独自のIPrincipal子孫を導入します。

public class BaseController : Controller 
{ 
    protected virtual new MyPrincipal User 
    { 
     get { return HttpContext.User as MyPrincipal; } 
    } 
} 

4)すべてのコントローラをこの新しいBaseControllerタイプから降下させます。

public class HomeController : BaseController 
{ 
    //... 
} 

5)独自のコントローラファクトリを作成して、プリンシパルがHttpContext/Threadに導入されていることを確認します。

public class MyControllerFactory : DefaultControllerFactory 
{ 
    protected override IController GetControllerInstance 
     (RequestContext requestContext, Type controllerType) 
    { 
     try 
     { 
      var controller = base.GetControllerInstance(requestContext, controllerType); 
      requestContext.HttpContext.User = Thread.CurrentPrincipal = new 
                MyPrincipal(); 
      return controller; 
     } 
     catch (Exception) 
     { 
      return base.GetControllerInstance(requestContext, controllerType); 
     } 
    } 
} 

6)コントローラファクトリをGlobal.asaxのApplication_Start()イベントハンドラに登録します。

var controllerFactory = new MyControllerFactory(); 
ControllerBuilder.Current.SetControllerFactory(controllerFactory); 

Voila、これでコントローラのどこにでも新しいユーザ(IMyPrincipal)を使用できるようになりました。例えば

:ASP.NET MVCを使用して、カミソリのページにあなたのIPrincipal実装アクセスできるようにする

public ActionResult Index() 
{ 
    ViewBag.Message = "Welcome to ASP.NET MVC!"; 

    ViewBag.UserId = User.UserId; 
    ViewBag.UserName = User.EmailAddress; 

    return View(); 
} 
1

最善の方法は、次のようにやっている:

  1. System.Security.Principal.IPrincipalインターフェイスを実装します。
  2. System.Security.Principal.IIdentityインターフェイスを実装します。
  3. Global.asaxでは、とIIdentityの両方の実装を維持する方法を定義します。void Application_AuthenticateRequest(Object, EventArgs)
  4. の実装が公開されるように、IPrincipalの拡張メソッドを作成します。
  5. 最後に、web.configファイルの前の拡張メソッドのネームスペースを<system.web.webPages.razor>に追加します。

最後に、タイプキャストの代わりにIIdentityのカスタム実装にアクセスすることができます。あなたは今、このようなあなたのカスタム実装にアクセスすることができます。

Hello @User.CustomIdentity().FirstName @User.CustomerIdentity().LastName! 

これらの手順は、ここに書かれただけでなく、詳細な記事の簡潔かつ簡単な説明です:http://rizzo7.blogspot.com/2012/04/mvc-30-razor-custom-principal-and.html

関連する問題