11

我正在構建一個內聯網應用程序使用MVC3與MSSQL後端。我有身份驗證和角色(通過自定義角色提供者)正常工作。我現在要做的是重寫User.Identity以允許像User.Identity.FirstName這樣的項目。但我無法找到任何代碼,會告訴我如何的WindowsIdentityMVC3 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來填充自定義主體。

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,而不是我的自定義主體。我究竟做錯了什麼?

編輯:

我註釋掉上面的代碼在Global.asax。 我已經覆蓋了AuthorizeAttribute使用C#:

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]
    • 身份

身份是accessable;但是,它仍然是WindowsIdentity CPrincipal只能在手錶中訪問,不能直接訪問。

編輯: 感謝所有對此有貢獻的人。您已經極大地擴展了我對各部分工作原理的理解。

我有兩種工作方式,所以我想我會分享。

選項1:覆蓋的授權請求在Global.asax中

這是一個我用下去。

我沒有使用Application_AuthenticateRequest,因爲(根據這個:HttpContext.Current.User is null even though Windows Authentication is on)用戶沒有在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全局處理everthing,選項2處理個人級別的所有內容。

+0

等等...什麼是事件處理程序?你不是在嘗試使用ASP.NET登錄控件嗎?這個活動位於哪裏,哪個活動與哪個活動相搭配? –

+0

我在內部網站上使用Windows身份驗證。此事件處理程序位於全局中。asax –

+0

global.asax中沒有OnAuthenticate處理程序。這可能是你遇到問題的原因。 –

回答

6

而不是這樣做,你應該重寫Global.asax中的Application_AuthenticateRequest方法,然後使用Current.User而不是HttpContext.Current.User(不知道爲什麼,但是有區別)。

然後,在控制器中訪問這個簡單的方法是創建一個擴展方法?類似這樣的:

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

那麼你可以只說User.Identity.IMyIdenty().FirstName。你也可以把它作爲一個屬性來做。

這裏是我使用的代碼:

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()); 
} 

現在,忽視了DependencyResolver東西和自定義身份驗證票證的東西,這是非常基本和正常工作對我來說。

然後,在我的應用程序,當我需要的信息從我的定製身份,我只是((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中執行身份驗證是您的工作。用戶當然是空的,因爲尚未發生認證。 –

2

What am I doing wrong?

可能[Authorize]屬性重寫您的更改。因此,而不是在WindowsAuthentication_OnAuthenticate方法這樣做你Global.asax編寫自定義Authorize屬性,就像這樣:

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; 
    } 
} 

,然後使用您的自定義,而不是屬性的默認之一:

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

在ASP。 NET MVC執行授權的標準方式是通過授權操作過濾器,而不是通過Global.asax中的事件。

+0

授權屬性不會覆蓋您的上下文。 –

+1

無論如何,在'Global.asax'中使用事件來執行ASP.NET MVC應用程序中的授權是個不好的做法。您應該使用自定義授權過濾器。 –

+1

他沒有在他的代碼中進行授權,他只是應用了自己的自定義主體,該參數仍應在global.asax中完成。 –