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.