Autenticação do Windows MVC3 substitui User.Identity
Eu estou construindo umintranet aplicação usando MVC3 com um backend MSSQL. Eu tenho autenticação e funções (através de um provedor de funções personalizadas) funcionando corretamente. O que estou tentando fazer agora é substituir User.Identity para permitir itens como User.Identity.FirstName. Mas não consigo encontrar nenhum código que me mostre como fazer isso no WindowsIdentity
Eu tentei escrever um provedor 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; }
}
e substituindo o WindowsAuthentication para preencher o principal 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;
}
}
Eu tenho um ponto de interrupção na função de autenticação e o principal está sendo preenchido; no entanto, quando eu coloco um ponto de interrupção nos controladores, o usuário é apenas seu RolePrincipal normal, em vez do meu principal personalizado. O que estou fazendo de errado?
EDITAR:
Eu comentei o código acima no global.asax. Eu tenho substituído o 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;
}
}
E ajustei meu principal para o seguinte:
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();
}
}
Agora, quando coloco um ponto de interrupção, o relógio mostra o seguinte no usuário:
Do utilizador[CSupport.Model.CPrincipal]IdentidadeIdentidade é acessível; no entanto, ainda é o CPrincipal do WindowsIdentity que só pode ser acessado no relógio e não pode ser acessado diretamente.
EDITAR: Obrigado a todos que contribuíram para isso. Você expandiu muito minha compreensão de como as várias partes funcionam.
Eu tenho duas maneiras de trabalhar, então eu pensei em compartilhar.
Opção 1: substituir a solicitação de autorização no Global.asax
Este é o que eu vou com.
Eu não usei Application_AuthenticateRequest porque (de acordo com isso:HttpContext.Current.User é nulo mesmo que a autenticação do Windows esteja ativada) o usuário não foi preenchido em um processo de autenticação do Windows e, portanto, não há nada que eu possa usar para obter as informações do usuário.
Application_AuthorizeRequest é o próximo da cadeia e acontece depois que a identidade do Windows é trazida.
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
Context.User = new FBPrincipal(HttpContext.Current.User.Identity);
}
}
Esta é a substituição do diretor
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);
}
}
É assim que você acessa as informações atualizadas no novo Principal que foi criado.
[Authorize(Roles = "super admin")]
public ActionResult Dashboard()
{
string firstname = (User as CPrincipal).userInfo.FirstName; // <--
DashboardModel dModel = reportDAL.GetChartData();
return View(dModel);
}
Opção 2: substituir o atributo AuthorizeAttribute
Este é o principal substituído (é o mesmo que acima)
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);
}
}
Aqui está a substituição do Atributo Autorizar
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;
}
}
É aqui que você altera qual AuthorizeAttribute usar e utilizar as novas informações.
[CAuthorize(Roles = "super admin")] // <--
public ActionResult Dashboard()
{
string firstname = (User as CPrincipal).userInfo.FirstName; // <--
DashboardModel dModel = reportDAL.GetChartData();
return View(dModel);
}
A opção 1 lida globalmente, a opção 2 lida com tudo em um nível individual.