ASP.NET MVC Creazione di un utente rappresentato
-
23-09-2019 - |
Domanda
Ho un app MVC in cui ho una classe utente e l'utente può anche impersonare un altro utente (utenti Amministratore soltanto).
Quindi io ho questo codice sotto che autentica la richiesta e istanzia la mia versione di una classe utente.
E 'quindi cerca di ottenere l'utente rappresentato dall'oggetto Session ma Session non è disponibile in questo metodo nel Global.asax.
Spero che questo ha un senso.
Come altro avrei potuto fare questo?
La mia domanda credo sia a che punto nei metodi global.asax si fa a ottenere l'accesso a oggetto Session per ogni richiesta?
protected void Application_OnAuthenticateRequest(object sender, EventArgs e)
{
IMylesterService service = ObjectFactory.GetInstance<IMylesterService>();
if (Context.User != null)
{
if (Context.User.Identity.IsAuthenticated)
{
User user = service.GetUser(Context.User.Identity.Name);
if (user == null)
throw new ApplicationException("Context.user.Identity.name is not a recognized user");
User impersonatedUser = (User)this.Session["ImpersonatedUser"];
if (impersonatedUser == null)
user.ImpersonatedUser = user;
else
user.ImpersonatedUser = impersonatedUser;
System.Threading.Thread.CurrentPrincipal = Context.User = user;
return;
}
}
User guest = service.GetGuestUser();
guest.ImpersonatedUser = guest;
System.Threading.Thread.CurrentPrincipal = Context.User = guest;
}
Nessuna soluzione corretta
Altri suggerimenti
Prova a creare un filtro di autorizzazione:
public class CustomAuthorizationFilter : AuthorizeAttribute
{
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
// perform your authorization here
// full access to HttpContext and session
}
}
È possibile quindi applicare questo attributo ai controller. Idealmente ci si dispone di un controller di base che tutti gli altri controller ereditano da e si potrebbe applicare l'attributo a livello di classe su quel controller. Poi tutte le richieste sarebbero autorizzate e applicare la rappresentazione come avete codificato sopra.
sessione non sarà disponibile durante AuthenticateRequest: Che cosa è necessario fare è tag le informazioni necessarie per l'Identity.userData; così per esempio se si dove utilizzare le forme di autenticazione effettuare le seguenti operazioni:
void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Context.User != null)
{
if (Context.User.Identity.IsAuthenticated)
{
// retrieve the value
var id = (FormsIdentity)Context.User.Identity;
var myvalue = id.Ticket.UserData; // "Here you are"
}
}
}
Per accedere utilizzando moduli che sarà necessario scrivere un cookie: MVC -> classe FormsAuthenticationService: IFormsAuthenticationService
public static void SetAuthenticationCookie(HttpContextBase context, FormsAuthenticationTicket ticket)
{
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName)
{
Value = FormsAuthentication.Encrypt(ticket),
Secure = FormsAuthentication.RequireSSL,
Domain = FormsAuthentication.CookieDomain,
HttpOnly = true,
Expires = DateTime.Now.AddMinutes(15)
};
if (!context.Request.IsSecureConnection && FormsAuthentication.RequireSSL)
{
throw new HttpException("Ticket requires SSL.");
}
context.Response.Cookies.Add(cookie);
}
public static FormsAuthenticationTicket CreateTicket(HttpContextBase context, string emailAddress, string userData, bool persist)
{
return new FormsAuthenticationTicket(1, emailAddress, DateTime.Now, DateTime.Now.AddMinutes(15), persist, userData, FormsAuthentication.FormsCookiePath);
}
Infine nel SignIn si sarebbe ora creare il ticket richiesto chiamando CreateTicket (...), e quindi si può scrivere fuori dal SetAuthenticationCookie (...).
public void SignIn(string userName, string password)
{
if(CheckUserValid(userName,password, out string email))
{
var ticket = CreateTicket(email, "Here you are", true);
SetAuthenticationCookie(HttpContext.Current.Base(), ticket);
}
}
Non ho mai usato, ma per scontato che lo stato della sessione viene assegnato durante l'AcquireRequestState:
public void Init(HttpApplication context)
{
context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
}
Ho avuto questo stesso problema di dover accedere sessione global.asax e infine risolto spostando il mio codice nel gestore AcquireRequestState
, che avviene dopo l'autenticazione è passato.
protected void Application_AcquireRequestState(Object sender, EventArgs e)
{
if (Request.IsAuthenticated && Context.Session != null)
{
// access Context.Session
}
}
Questa spara un sacco e il contesto attuale non sempre avere un oggetto sessione valida, quindi il controllo.
Modifica : dovuto aggiungere il controllo per IsAuthenticated troppo - è stato sempre un errore di nulla quando disconnesso. Funziona alla grande ora.