CustomPrincipal cd.

Jakiś czas temu pokazałem w tym artykule sposób rozszerzenia możliwości obiektu zalogowanego użytkownika (Context.User). Problemem tamtego rozwiązania jest to, iż na końcu każdego żądania tworzony jest na nowo obiekt CustomPrincipal, co w finalnym efekcie znacząco wpływa na wydajność aplikacji. Oczywiście jest to zależne od ilości rzeczy implementowanych przez nasz obiekt. W celu naprawy tego niedociągnięcia należy nieznacznie zmodyfikować kod klasy z pliku Global.asax.cs – zapraszam do lektury.

Kluczową zmianą jest rezygnacja ze zdarzenia Application_PostAuthenticateRequest na rzecz zdarzenia Application_PreRequestHandlerExecute. Przewaga drugiego zdarzenia jest znacząca, ponieważ w kontekście naszej aplikacji mamy dostęp do sesji użytkownika, a ona jest sposobem rozwiązania problemu. Daje możliwość przechowania obiektu CastomPrincipal, a tym samym nie wymusza tworzenia go na nowo. Implementacja rozwiązania to indywidualna sprawa programisty, ja postąpiłem w sposób przedstawiony poniżej.

W pierwszej kolejności zaimplementowałem metodę odpowiedzialną za zwrócenie obiektu CustomPrincipal:

private System.Security.Principal.IPrincipal GetPrincipal()
{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    FormsAuthenticationTicket authTicket = null;
    try
    {
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch (Exception ex)
    {
        return Context.User;
    }

    if (null == authTicket)
    {
        FormsAuthentication.RedirectToLoginPage();
        return null;
    }
    else
    {
        var roleUser = Context.User as RolePrincipal;
        return new CustomPrincipal(
			new FormsIdentity(authTicket), 
			roleUser.IsRoleListCached ? roleUser.GetRoles() : Roles.GetRolesForUser()
			);
    }
}

W kolejnym, ostatnim kroku wypełniłem metodę Application_PreRequestHandlerExecute:

const string CUSTOM_PRINCIPAL = "CustomPrincipal";

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        if (Context.Session != null)
        {
		    if (Context.Session[CUSTOM_PRINCIPAL] == null)
		    {
			    Context.Session[CUSTOM_PRINCIPAL] = GetPrincipal();
		    }
            Context.User = Context.Session[CUSTOM_PRINCIPAL] as CustomPrincipal;
	    }
        else
	    {
		    Context.User = GetPrincipal();
	    }
    }
}

Tym oto sposobem, szybkim i łatwym w implementacji, można rozwiązać poważny wydajnościowy problem aplikacji.

Promuj

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *