CustomPrincipal

UPDATED: Zachęcam do zapoznania się z kontynuacją tego tematu – CustomPrincipal cd.

Obiekt użytkownika wykonującego żądanie (Context.User) jest powszechnie znany. Dzięki niemu w prosty i szybki sposób sprawdzimy, czy osobnik poruszający się po naszej aplikacji jest zalogowany oraz jaki jest jego login. Dodatkowo, jeśli zrzutujemy ten obiekt na klasę, np. RolePrincipal, to otrzymamy dodatkowe możliwości tego obiektu (wymagana deklaracja roleManagera w web.config). A co jeśli chcielibyśmy, aby ten obiekt zawierał nasze właściwości oraz metody? W tym artykule zaprezentuję co należy wykonać, aby obiekt User implementował naszą zawartość.

W pierwszej kolejności dodajemy nową klasę do projektu aplikacji. Ta musi dziedziczyć po GeneralPrincipal. Dodajemy dwie testowe właściwości: UserLogin oraz UserRoles. Definiujemy konstruktor, do którego przesyłać będziemy obiekt FormsIdentity i role użytkownika. Na koniec wywołujemy konstruktor z typu bazowego, po którym dziedziczymy oraz przypisujemy wartości zmiennych. Wszystko to może wyglądać w następujący sposób:

public class CustomPrincipal : System.Security.Principal.GenericPrincipal
{
    public string UserLogin { get; private set; }
    public string[] UserRoles { get; private set; }

    public CustomPrincipal(System.Web.Security.FormsIdentity identity, string[] userRoles)
        : base(identity, userRoles)
    {
        UserLogin = identity.Name;
        UserRoles = userRoles;
        //LoadDetails();
    }
}

Następnym krokiem jest deklaracja roleManagera w pliku web.config (można to uczynić tak, jak w tym artykule). Potem dodajemy do projektu Global Application Class, w której deklarujemy zdarzenie jak poniżej:

void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (Request.IsAuthenticated)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication
        	.Decrypt(Context.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
        var user = Context.User as RolePrincipal;

        CustomPrincipal customPrincipal = new CustomPrincipal(new FormsIdentity(authTicket), user.GetRoles());
        Context.User = customPrincipal;
    }
}

W powyższym kodzie w pierwszej kolejności pobieramy ciasteczka, stworzone po poprawnym zalogowaniu użytkownika. Te są dekodowane, a z nich tworzony jest ticket autoryzacyjny wykorzystywany do stworzenia obiektu FormsIdentity, który finalnie należy wykorzystać podczas tworzenia obiektu CustomPrincipal. Na koniec należy jeszcze podmienić obiekt użytkownika.

Efekt osiągnięty. W tym momencie możemy do woli rozwijać klasę CustomPrincipal. Przykładowo:

public class CustomPrincipal : System.Security.Principal.GenericPrincipal
{
    public string FullName { get; private set; }
    public DateTime BirthDate { get; private set; }

    // ...

    public bool HasRight(SystemRight right)
    {
        // ...
    }

    private void LoadDetails()
    {
        var user = DBHelper.GetModel().User
            .FirstOrDefault(a => a.UserId == 
            	new Guid(System.Web.Security.Membership.GetUser().ProviderUserKey.ToString()));

        FullName = "{FirstName} {LastName}".FormatWith(user);
        BirthDate = user.BirthDate;
    } 
}

oraz wykorzystanie:

protected void Page_Load(object sender, EventArgs e)
{
    if (User.Identity.IsAuthenticated)
    {
        var user = User as CustomPrincipal;
        lFullName.Text = user.FullName;

        if (user.HasRight(SystemRight.VisitMoon))
        {
            // ...
        }
    }
}

Jak widać powyżej, jest to tylko mały przykład możliwości rozwoju klasy CustomPrincipal. Myślę, że można ulepszać ją w każdym kierunku, a jej granice wyznacza tylko wyobraźnia programisty.

Promuj

Dodaj komentarz

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