11

私はイントラネットアプリケーションをMVC3を使用してMSSQLバックエンドで構築しています。認証とロール(カスタムロールプロバイダを使用)が適切に機能しています。私が今しようとしているのは、User.Identity.FirstNameのような項目を許可するためにUser.Identityをオーバーライドすることです。MVC3 Windows認証オーバーライドUser.Identity

public class CPrincipal : WindowsPrincipal 
{ 
    UserDAL userDAL = new UserDAL(); 
    public CPrincipal(WindowsIdentity identity) 
     : base(identity) 
    { 
     userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]); 
     this.identity = identity; 
    } 
    public UserInfo userInfo { get; private set; } 
    public WindowsIdentity identity { get; private set; } 
} 

およびカスタムプリンシパルを移入するWindowsAuthenticationをオーバーライド:しかし、私はWindowsIdentity

でこれを行う方法を私が表示されます任意のコードを見つけることができない私は、カスタムプロバイダを作成しようとしています。

void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e) 
    { 
     if (e.Identity != null && e.Identity.IsAuthenticated) 
     { 
      CPrincipal cPrincipal = new CPrincipal(e.Identity); 
      HttpContext.Current.User = cPrincipal; 
     } 
    } 

私は認証機能にブレークポイントを持ち、プリンシパルにデータが入力されています。しかし、コントローラにブレークポイントを置くと、ユーザーはカスタムプリンシパルではなく通常のRolePrincipalになります。私は間違って何をしていますか?

EDIT:

私は、Global.asaxの中で上記のコードをコメントアウト。 私はC#を使用してAuthorizeAttributeをオーバーライドしています

public class CAuthorize : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     bool authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 


     IIdentity user = httpContext.User.Identity; 
     CPrincipal cPrincipal = new CPrincipal(user); 
     httpContext.User = cPrincipal; 

     return true; 
    } 

} 

そして次に私のプリンシパルを調整:

public class CPrincipal : IPrincipal 
{ 
    private UserDAL userDAL = new UserDAL(); 
    public CPrincipal(IIdentity identity) 
    { 
     userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]); 
     this.Identity = identity; 
    } 
    public UserInfo userInfo { get; private set; } 

    public IIdentity Identity { get; private set; } 

    public bool IsInRole(string role) 
    { 
     throw new NotImplementedException(); 
    } 
} 

私はブレークポイントを置いたときに今、私は、時計がユーザーに次のように示しています

  • ユーザー
    • [CSupport.Model.CPrincipal]
    • アイデンティティ

アイデンティティがアクセス可能です。ただし、それでもWindowsIdentity CPrincipalは時計でのみアクセスでき、直接アクセスすることはできません。

編集: これに寄与した皆様に感謝します。あなたは、さまざまな部品がどのように機能するかについての私の理解を大幅に拡大しました。

私は両方の方法で働くことができたので、私は分かち合うと思った。

オプション1:これは私はつもりですGlobal.asaxの

に承認要求をオーバーライドします。

(これに応じて:HttpContext.Current.User is null even though Windows Authentication is on)私はApplication_AuthenticateRequestを使用しませんでした。ユーザーはWindows認証プロセスで入力されていないため、ユーザー情報を取得するために使用できるものはありません。

Application_AuthorizeRequestはチェーン内の次のもので、ウィンドウのアイデンティティが取り込まれた後に発生します。

protected void Application_AuthorizeRequest(object sender, EventArgs e) 
    { 
     if (User.Identity.IsAuthenticated && Roles.Enabled) 
     { 
      Context.User = new FBPrincipal(HttpContext.Current.User.Identity); 
     } 
    } 

これはこれは、作成した新しい校長内の更新情報にアクセスする方法である校長

public class CPrincipal : IPrincipal 
{ 
    private UserDAL userDAL = new UserDAL(); 
    public CPrincipal(IIdentity identity) 
    { 
     userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]); 
     this.Identity = identity; 
    } 
    public UserInfo userInfo { get; private set; } 

    public IIdentity Identity { get; private set; } 

    public bool IsInRole(string role) 
    { 
     return userDAL.IsUserInRole(userInfo.UserName, role); 
    } 
} 

のオーバーライドです。

[Authorize(Roles = "super admin")] 
    public ActionResult Dashboard() 
    { 
     string firstname = (User as CPrincipal).userInfo.FirstName; // <-- 
     DashboardModel dModel = reportDAL.GetChartData(); 
     return View(dModel); 
    } 

オプション2:これは、オーバーライドされたプリンシパル(これは上記と同じ)であるAuthorizeAttribute

をオーバーライドここ

public class CPrincipal : IPrincipal 
{ 
    private UserDAL userDAL = new UserDAL(); 
    public CPrincipal(IIdentity identity) 
    { 
     userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]); 
     this.Identity = identity; 
    } 
    public UserInfo userInfo { get; private set; } 

    public IIdentity Identity { get; private set; } 

    public bool IsInRole(string role) 
    { 
     return userDAL.IsUserInRole(userInfo.UserName, role); 
    } 
} 

は、承認のオーバーライドが属性である

public class CAuthorize : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     bool authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 


     IIdentity user = httpContext.User.Identity; 
     CPrincipal cPrincipal = new CPrincipal(user); 
     httpContext.User = cPrincipal; 

     return true; 
    } 

} 

これは、使用するAuthorizeAttributeを変更し、新しい情報を利用する場所です。

[CAuthorize(Roles = "super admin")] // <-- 
    public ActionResult Dashboard() 
    { 
     string firstname = (User as CPrincipal).userInfo.FirstName; // <-- 
     DashboardModel dModel = reportDAL.GetChartData(); 
     return View(dModel); 
    } 

オプション1は、すべてのものをグローバルに処理し、オプション2は、すべてのレベルを個別に処理します。

+0

待機...そのイベントハンドラとは何ですか?あなたはあなたのASP.NETログインコントロールを使用しようとしていないのですか?このイベントはどこにありますか? –

+0

イントラネットサイトでWindows認証を使用しています。このイベントハンドラはグローバルに存在します。asax –

+0

global.asaxにはOnAuthenticateハンドラはありません。それはおそらくあなたが問題を抱えている理由です。 –

答えて

6

このようにするのではなく、global.asaxでApplication_AuthenticateRequestメソッドをオーバーライドしてから、HttpContext.Current.UserではなくCurrent.Userを使用する必要があります(理由は分かりませんが、違いがあります)。

次に、コントローラでこれにアクセスする簡単な方法は、拡張メソッドを作成することです。このようなもの:

public static class IIdentityExtensions { 
    public static IMyIdentity MyIdentity(this IIdentity identity) { 
     return (IMyIdentity)identity; 
    } 
} 

User.Identity.IMyIdenty().FirstNameと言うことができます。あなたはおそらくプロパティとして同様にこれを行うことができます。ここで

は、私が使用するコードです:DependencyResolverのものとカスタム認証チケットのものを無視して、

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
{ 
    FormsAuthenticationTicket authTicket = FormsAuthentication 
     .Decrypt(authCookie.Value); 
    var identity = new MyIdentity(authTicket.Name, "Forms", 
     FormsAuthenticationHelper.RetrieveAuthUserData(authTicket.UserData)); 
    Context.User = new GenericPrincipal(identity, 
     DependencyResolver.Current.GetService<ISecurityHandler>() 
      .GetRoles(identity.Name).ToArray()); 
} 

、これはかなり基本的なものと私のために正しく動作します。

私のカスタムアイデンティティの情報が必要な場合は、((IMyIdentity)User.Identity).FirstNameまたは必要なものをキャストしてください。それはロケット科学ではなく、機能します。

+0

私はちょうどauthenticaterequest部分を試して、得ました:HttpContext.Current.Userはnullであり、Currentは存在しません。 '保護され、ボイドのApplication_AuthenticateRequest(オブジェクト送信者、EventArgsの電子) { 場合(HttpContext.Current.User.Identity!= nullの&& HttpContext.Current.User.Identity.IsAuthenticated) { HttpContext.Current.User =新しいCPrincipal(のHttpContext .Current.User.Identity); } } ' –

+0

@TobyJones - 私の編集を参照してください。 AuthenticateRequestで認証を行うのはあなたの仕事です。認証はまだ行われていないため、ユーザーはもちろんNullです。 –

2

What am I doing wrong?

おそらく、[Authorize]属性が変更を上書きしている可能性があります。だからではなく、あなたのGlobal.asaxそうのように、カスタムAuthorize属性を記述におけるWindowsAuthentication_OnAuthenticate方法でこれを行う:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 


     var user = httpContext.User as WindowsIdentity; 
     CPrincipal cPrincipal = new CPrincipal(user); 
     httpContext.User = cPrincipal; 

     return true; 
    } 
} 

、その後、デフォルトの代わりにカスタム属性を使用します。ASPで

[MyAuthorize] 
public ActionResult SomeAction() 
{ 
    // User.Identity will be your custom principal here 
} 

。 NET MVCでは、認可を実行するための標準的な方法は、認可アクションフィルタによるものであり、Global.asaxのイベントによるものではありません。

+0

Authorize属性はコンテキストをオーバーライドしません。 –

+1

とにかく、 'Global.asax'のイベントを使ってASP.NET MVCアプリケーションで権限を実行するのは悪い習慣です。代わりにカスタム認証フィルタを使用する必要があります。 –

+1

彼は彼のコードで認可をしていません、彼はただ彼のカスタムプリンシパルを適用しています。それはafricaがまだglobal.asaxで行われるべきです。 –