11

Estoy construyendo una aplicación de intranet usando MVC3 con un back-end MSSQL. Tengo la autenticación y los roles (a través de un proveedor de funciones personalizadas) que funcionan correctamente. Lo que intento hacer ahora es anular User.Identity para permitir elementos como User.Identity.FirstName. Pero no puedo encontrar ningún código que me va a mostrar cómo hacer esto en WindowsIdentityMVC3 Autenticación de Windows anula User.Identity

He intentado escribir un proveedor personalizado:

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

y anulando el WindowsAuthentication para poblar el director personalizado.

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

Tengo un punto de interrupción en la función de autenticación y el principal se está rellenando; sin embargo, cuando pongo un punto de interrupción en los controladores, el usuario es su RolePrincipal normal, en lugar de mi principal personalizado. ¿Qué estoy haciendo mal?

EDIT:

comenté a cabo el código anterior en el Global.asax. he anulado la AuthorizeAttribute usando 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; 
    } 

} 

y ajustado mi representada a lo siguiente:

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

Ahora cuando pongo un punto de interrupción en, el reloj muestra lo siguiente en el usuario:

  • usuario
    • [CSupport.Model.CPrincipal]
    • Identidad

identidad es accesible; sin embargo, sigue siendo WindowsIdentity CPrincipal solo se puede acceder en el reloj y no se puede acceder directamente.

EDITAR: Gracias a todos los que contribuyeron a esto. Has ampliado mucho mi comprensión de cómo funcionan las diversas partes.

que tiene dos maneras de trabajar, así que pensé que iba a compartir.

Opción 1: Anulación de la solicitud de autorizar, en Global.asax

Este es el que voy con.

No utilicé Application_AuthenticateRequest porque (de acuerdo con esto: HttpContext.Current.User is null even though Windows Authentication is on) el usuario no se ha rellenado en un proceso de autenticación de Windows y, por lo tanto, no hay nada que pueda usar para obtener la información del usuario.

Application_AuthorizeRequest es el siguiente en la cadena y pasa después de la identidad ventanas se trae.

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

Esta es la anulación del Principal

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

Esta es la forma de acceder a la información actualizada en el nuevo director que se ha creado.

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

Opción 2: Reemplazar el AuthorizeAttribute

Este es el principal anulado (Es el mismo que el anterior)

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

Aquí está la anulación de la Authorize Atributo

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

} 

Aquí es donde cambia qué AuthorizeAttribute utilizar y utilizar la nueva información ción.

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

Opción 1 Everthing maneja a nivel mundial, la opción 2 se encarga de todo a nivel individual.

+0

Espera ... ¿Qué es ese controlador de eventos? No estás tratando de usar el control de inicio de sesión de ASP.NET, ¿verdad? ¿Dónde está ubicado este evento y en qué evento está vinculado? –

+0

Estoy usando la autenticación de Windows en un sitio de intranet. Este controlador de eventos está en el global.asax –

+0

No hay controlador OnAuthenticate en global.asax. Esa es probablemente la razón por la que estás teniendo problemas. –

Respuesta

6

En lugar de hacerlo de esta manera, debe anular el método Application_AuthenticateRequest en global.asax, luego use Current.User en lugar de HttpContext.Current.User (no estoy seguro de por qué, pero hay una diferencia).

Entonces, ¿una forma fácil de acceder a esto en su controlador es crear un método de extensión? Algo como esto:

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

a continuación, sólo se puede decir User.Identity.IMyIdenty().FirstName. Probablemente también puedas hacer esto como una propiedad.

Este es el código que utilizo:

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

Ahora, haciendo caso omiso de las cosas y las cosas DependencyResolver billete de autenticación personalizada, esto es bastante básico y funciona correctamente para mí.

Luego, en mi aplicación, cuando necesito información de mi identidad personalizada, solo la echo con ((IMyIdentity)User.Identity).FirstName o lo que sea que necesite. No es ciencia espacial, y funciona.

+0

Intenté solo la parte authenticaterequest y obtuve: HttpContext.Current.User es nulo y Current does not exists. 'Protected void Application_AuthenticateRequest (object sender, EventArgs e) { si (HttpContext.Current.User.Identity! = Null && HttpContext.Current.User.Identity.IsAuthenticated) { HttpContext.Current.User = new CPrincipal (HttpContext .Current.User.Identity); } } ' –

+0

@TobyJones - ver mi edición. Es su trabajo hacer la autenticación en AuthenticateRequest. El usuario es, por supuesto, nulo porque aún no se ha autenticado. –

2

What am I doing wrong?

Probablemente el atributo [Authorize] está anulando los cambios. Así que en lugar de hacerlo en el método WindowsAuthentication_OnAuthenticate en su Global.asax escribir una costumbre Authorize atributo, así:

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

y luego utilizar el atributo personalizado en lugar de la opción por defecto:

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

En ASP. NET MVC la forma estándar de realizar la autorización es a través de filtros de acción de autorización, no a través de eventos en Global.asax.

+0

El atributo Autorizar no anula su contexto. –

+1

De todos modos, es una mala práctica usar eventos en 'Global.asax' para realizar la autorización en una aplicación ASP.NET MVC. Debería usar filtros de autorización personalizados en su lugar. –

+1

No está haciendo una autorización en su código, solo está aplicando su principal personalizado, que afaik aún se debe hacer en global.asax. –

Cuestiones relacionadas