2016-09-12 9 views
5

Webアプリケーション用にASP.NET MVC 5を使いたいです。私はwindows authenticationを使用する必要があります。Windows認証でASP.NET MVC 5のセッションにユーザー情報を読み込むことはできますか?

windows authenticationを使用すると、ユーザー情報(ユーザーIDとロール)を読み取って、Sessionに保存するのに最適な場所はどこですか?

私はこのようなデータベースからのユーザー名でユーザー情報を取得するためのメソッドがあります。セッションでは決して、決して決してストアユーザの詳細情報:

public class CurrentUser 
    { 
     public int UserId { get; set; } 

     public string UserName { get; set; } 

     public Roles Roles { get; set; } 
    } 

    public enum Roles 
    { 
     Administrator, 
     Editor, 
     Reader 
    } 

    public class AuthService 
    { 
     public CurrentUser GetUserInfo(string userName) 
     { 
      var currentUser = new CurrentUser(); 

      //load from DB 

      return currentUser; 
     } 
    } 

答えて

2

あなたは、(1)ユーザー情報を取得するのに最適な場所と、(2)セッションに保存する方法の2つの質問をしました。私は答えるだろう(1)そしてそうすることで、おそらくセッションに追加情報を入れる必要はないことを示しているだろう。

あなたのアプリケーションではWindows認証が使用されていると言われています。これは、アプリケーションが要求を受け取る前にIIS/HttpListenerによってユーザーが認証されていることを意味します。リクエストを受け取ったらWindowsPrincipalHttpContext.Userになります。これにより、ウィンドウズのユーザー名と広告の役割はすでに確立されていますが、データベースに格納されている追加の役割を使用したいと考えています...

IAuthorizationFilterと一緒に仕事をしてください。この方法に従うことで、データベースからフェッチする追加の役割やその他の情報がコントローラメソッドで利用できます。さらに重要なことは、ユーザーの資格情報を確認する必要がある追加のライブラリコードです。

.Net 4.5より前のバージョンでは、WindowsPrincipalに追加情報を追加する場合は、システム提供のユーザーをIPrincipalインターフェイスを実装した別のオブジェクトに置き換えてください。このアプローチはまだ利用可能です(と私は何をお勧めします).Net 4でWindows Identity Foundation(WIF)の導入以来。図5のWindowsPrincipalは、 System.Security.Claims.ClaimsIdentityClaimsIdentityから派生したもので、システム提供のプリンシパルに追加の役割(およびその他の有用な情報)を追加することができます。しかし、いくつかの人々が発見したように、Windowsにバグ/機能があり、プログラムで追加されたロールをチェックするときに例外The trust relationship between the primary domain and the trusted domain failedがスローされる可能性があります。私たちは、これを避ける簡単で信頼性の高い方法は、ユーザーをGenericPrincipalに置き換えることであることが判明しました。必要

ステップ:

(1)IAuthorizationFilterを作成します。

class MyAuthorizationFilter : IAuthorizationFilter 
{ 
    AuthService _authService; 

    public MyAuthorizationFilter(AuthService authService) 
    { 
     _authService = authService; 
    } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var principal = filterContext.HttpContext.User; 

     if (principal.Identity != null && principal.Identity.IsAuthenticated) 
     { 
      // Add username (and other details) to session if you have a need 
      filterContext.HttpContext.Session["User"] = principal.Identity.Name; 

      // get user info from DB and embue the identity with additional attributes 
      var user = _authService.GetUserInfo(principal.Identity.Name); 

      // Create a new Principal and add the roles belonging to the user 
      GenericPrincipal gp = new GenericPrincipal(principal.Identity, user.RoleNames.ToArray()); 
      filterContext.HttpContext.User = gp; 
     } 
    } 
} 

(2)フィルタを登録します。これはコントローラレベルで、またはグローバルに登録することができます。通常は、App_Start\FilterConfig.csでこれを行います。

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new MyAuthorizationFilter(new AuthService())); 
    } 
} 

(3)ユーザ識別およびその他の資格情報についての質問に答えるために、アプリケーションコードで提供GenericPrincipalを使用してください。例えばあなたのコントローラのメソッドでは、あなたのフィルタによってGenericPrincipalに保存されているユーザー名やその他の "申し立て"(例:電子メールアドレス)にアクセスできます。

 public ActionResult Index() 
     { 
      ViewBag.Name = HttpContext.User.Identity.Name; 
      if(HttpContext.User.IsInRole("Administrator")) 
      { 
       // some role-specific action 
      } 
      return View(); 
     } 

あなたが主な役割を記録する組み込みのメカニズムを使用しましたので、あなたはどこにでもHttpContext.UserSystem.Threading.Thread.CurrentPrincipalを使用してからユーザーの詳細にアクセスすることができます。コントローラのメソッドでAuthorizeAttributeを使用して、特定のロールまたはユーザーが使用できるアクションを宣言することもできます。例えば

public class HomeController : Controller 
    { 
     [Authorize(Roles = "Administrator")] 
     public ActionResult Admin() 
     { 
      return View(); 
     } 

私は、これは

-Rob

+0

Robありがとうございました。あなたの役割を果たすあなたのソリューションは素晴らしいですが、私はうんざりして、ユーザーIDなどのデータベースからいくつかの情報を取得するような理由でセッションを行うためにユーザーIDを取得する必要があります。 :-)私はこれを行うための最良の場所がどこか分かりません。ありがとう。 – Jenan

+0

こんにちはジェナン。 AuthorizationFilterのセッションにユーザー名を追加する必要がある場合(これを表示するために回答を更新しました)、追加することができますが、なぜこれを行う必要があるのか​​分かりません。 HttpConext.User(コントローラ内)を使用して任意のコードからプリンシパル(およびそこからIdentity.Username)にアクセスすることができます。また、ライブラリコードを深く理解していれば、System.Threading.Thread.CurrentPrincipalを使用できます。 – Rob

+0

ロブ、ありがとうございました。この答えは私にとっては素晴らしいことです。 – Jenan

1

まず第一に。真剣に。ただしないでください。

Windows認証を使用している場合、ユーザーはADになります。ユーザー情報を取得するためにADを使用しています。マイクロソフトはMSDN articleがこれを行う方法を説明しています。

ロングとショートはあなたがUserIdentityのサブクラスを作成し、ユーザーに返すようにしたい追加のプロパティでそれを拡張することである:上記のサンプルコードで

[DirectoryRdnPrefix("CN")] 
[DirectoryObjectClass("inetOrgPerson")] 
public class InetOrgPerson : UserPrincipal 
{ 
    // Inplement the constructor using the base class constructor. 
    public InetOrgPerson(PrincipalContext context) : base(context) 
    { 
    } 

    // Implement the constructor with initialization parameters.  
    public InetOrgPerson(PrincipalContext context, 
         string samAccountName, 
         string password, 
         bool enabled) 
         : base(context, 
           samAccountName, 
           password, 
           enabled) 
    { 
    } 

    InetOrgPersonSearchFilter searchFilter; 

    new public InetOrgPersonSearchFilter AdvancedSearchFilter 
    { 
     get 
     { 
      if (null == searchFilter) 
       searchFilter = new InetOrgPersonSearchFilter(this); 

      return searchFilter; 
     } 
    } 

    // Create the mobile phone property.  
    [DirectoryProperty("mobile")] 
    public string MobilePhone 
    { 
     get 
     { 
      if (ExtensionGet("mobile").Length != 1) 
       return null; 

      return (string)ExtensionGet("mobile")[0]; 
     } 

     set 
     { 
      ExtensionSet("mobile", value); 
     } 
    } 

    ... 
} 

、プロパティをバインドに追加されますADのユーザのmobileフィールドに送信する。これは、図のようにプロパティを実装してExtensionSetを入力し、プロパティにDirectoryPropertyという属性を付けてバインドするフィールドを指定することで行います。

クラスの属性は、広告の設定方法と一致する必要があります。

これが実装されると、User.Identityを参照するだけで値を取得できます。たとえば、User.Identity.MobilePhoneは、ユーザーのADからmobileフィールドを返します。

+0

を役に立てば幸いClaimsIdentity

についての詳細はMSDNを参照してください答えをいただき、ありがとうございます。なぜユーザー情報をセッションに保存しないのですか? – Jenan

+0

まず、セッションは一般的に控えめに使用する必要があります。セッションは必要な悪です。頻繁に使うべきではないし、気まぐれに使うべきではありません。第二に、セッションは本質的に安全ではありません。クッキーを設定するときにHTTPSと 'HTTPOnly'や' Secure'のようなフラグを使うことで、それらをより安全にする方法はありますが、そうでなければ存在しない脆弱性はまだ残っています。少なくとも認証のようなものに頼らざるを得ないので、あなたができることは露出を軽減することです。これは、ユーザーを検索するための情報の必要性だけを含めることによって行われます。 –

+0

例えば、ユーザーIDのようなものは、ユーザーIDが存在するデータベースへのアクセスがなければ意味がありません。そのため、セッションCookieに含めることは比較的無害ですが、名前、アドレス、電子メール、電話、そのセッションでは、その個人情報をすべて漏らす可能性があります。 –

関連する問題