Poznáváme C# a Microsoft .NET 79. díl – Bezpečnost založená na rolích

Po článcích věnujících se systému zabezpečení CAS se dnes již plnou silou vrhneme na druhý systém zabezpečení, který je obsažen v .NET frameworku. Tímto bezpečnostním systémem je bezpečnost založená na rolích.
Poznáváme C# a Microsoft .NET 79. díl – Bezpečnost založená na rolích

Základní koncept

I přesto, že jsme během článků o systému zabezpečení CAS nepoznali úplnou množinu možností, kterou nám tento systém nabízí, myslím, že mohu označit CAS za velmi propracovaný systém zabezpečení.  Ovšem ne vždy nám k řízení přístupu ke chráněnému zdroji či operaci stačí systém CAS. V častých případech potřebujeme pro rozhodnutí udělení přístupu informaci o aktuálně pracujícím uživateli. Tuto problematiku řeší systém bezpečnosti založený na rolích. Stejně jako v operačních systémech se zde, jak název naznačuje, pracuje hlavně nikoli s jednotlivými uživateli (i když je to také možné), ale s rolemi.

Tento způsob je doporučen z jednoduchého důvodu. Pokud jsou na úrovni aplikace používány role, je mnohem snazší povolit dalším uživatelům přístup k chráněným operacím a zdrojům. Protože v případě užívání rolí je tohoto úkonu možno dosáhnout obsazením uživatele do dané role namísto doplnění aplikace o konkrétního uživatele a její rekompilaci. V systému zabezpečení založeného na rolích se při vykonávání kontroly role či identity nepoužívá procházení zásobníku (stack walking) jako se tomu děje v případě CAS. Tím pádem jsou také všechny kontroly rychlejší.

Principál

Za účelem reprezentace kontextu zabezpečení uživatele existují v .NET frameworku objekty typu principál. Pomocí těchto objektů, které mají jedno společné rozhraní IPrincipal, je možné zjistit zda-li je uživatel obsazen do určité role. Tyto objekty jsou automaticky modulem CLR připojovány k jednotlivým vláknům aplikace, tím pádem každé vlákno běží s bezpečnostním kontextem určitého uživatele. Typ objektu principálu je závislý na použitém způsobu autentikace. Standardně implementovaná je podpora pro:

• Ověřování pomocí mechanismu systému Windows
• Ověřování pomocí služby .NET passport
• Ověřování pomocí ASP .NET

Pokud by někomu tyto možnosti nestačily (což nevidím jako nereálné), je možné implementovat rozhraní IPrincipal vlastním typem, používaným pro daný způsob autentikace. Na rozhraní IPrincipal je obsažena jediná metoda, kterou je metoda IsInRole, pomocí které zjistíme jestli je uživatel, jehož kontext je reprezentován objektem principálu, obsazen do specifické role.

//nastavime politiku vazani identity       AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
           
//ziskame objekt predstavujici uzivatele
IPrincipal principal = Thread.CurrentPrincipal;
//zjistime jestli je obsazen v roli Administrator
bool isAdmin = principal.IsInRole("Administrator");
if (isAdmin)
{
   Console.WriteLine("Uzivatel je obsazen v roli Administrator");
}
else
{
    Console.WriteLine("Uzivatel neni obsazen v roli Administrator");
}

Běhové prostředí CLR z bezpečnostních důvodů standardně nenaplní vlastnost CurrentPrincipal vlákna objektem představujícího kontext uživatele. Aby se tak dělo, je potřeba nastavit politiku aplikační domény pro vázání  objektů principálů s vlákny, což zařídíme použitím metody SetPrincipalPolicy na objektu aplikační domény. V našem příkladu je použito svázání s účtem systému Windows (PrincipalPolicy.WindowsPrincipal). Poté je z aktuální vlákna vyzvednut objekt principála a použita na něm metoda IsInRole pro zjištění, jestli je uživatel obsazen do role Administrator.

Ke zjišťování rolí, do nichž je aktuální uživatel obsazen, se může hodit výčet WindowsBuiltInRole, který obsahuje názvy častých rolí vyskytujících se v instalacích systémů Windows NT, Windows 2000 a Windows XP.

//ziskani kontextu aktualniho uzivatele
IPrincipal principal = Thread.CurrentPrincipal;
//ziskani hodnot vyctu WindowsBuiltInRole
WindowsBuiltInRole[] roles = (WindowsBuiltInRole[]) Enum.GetValues(typeof(WindowsBuiltInRole));
//testovani roli uzivatele
foreach (WindowsBuiltInRole role in roles)
{
      if (principal.IsInRole(role.ToString()))
      {
         Console.WriteLine("Aktualni uzivatel je obsazen do role {0}", role.ToString());
      }
}

Identita uživatele

Kromě zjištění toho, jestli je uživatel obsazen do určité role, je možné získat informace o jeho identitě. Identity jsou podobně jako v případě principálů objekty s jedním společným rozhraním. Tímto rozhraním je rozhraní IIdentity a podobně jako u principálu i zde typ použitého objektu souvisí s použitým způsobem autentikace. K získání objektu identity můžeme použít vlastnosti Identity na objektu principála.

//ziskani objektu aktualniho uzivatele
IPrincipal principal = Thread.CurrentPrincipal;
//ziskani identity aktualniho uzivatele
IIdentity identity = principal.Identity;

//vypsani informaci o identite
Console.WriteLine("Zpusob autentikace: {0}", identity.AuthenticationType);
Console.WriteLine("Je autentikovan: {0}", identity.IsAuthenticated);
Console.WriteLine("Jmeno uzivatele: {0}", identity.Name);

Tímto způsobem bychom postupovali, pokud bychom chtěli používat programování oproti společnému rozhraní IIdentity. Pokud používáme mechanismu ověřování systému Windows, jsou ve skutečnosti používány objekty typu WindowsIdentity, které nám dovolují zjistit specifičtější informace o identitě uživatele. Rozhraní tohoto typu můžeme zajistit buď přetypováním vlastnosti Identity objektu principála, nebo použitím metody GetCurrent na objektu typu WindowsIdentity, což je použito v následujícím příkladu.

//ziskame aktualni identitu uzivatele windows
WindowsIdentity identity = WindowsIdentity.GetCurrent();
//zjistime, zda-li je uzivatel typu guest
Console.WriteLine("Je host? {0}", identity.IsGuest);
//zjistime, zda-li je uzivatel typu system
Console.WriteLine("Je system? {0}", identity.IsSystem);
//zjistime, zda-li je uzivatel anonymni
Console.WriteLine("Je anonymni? {0}", identity.IsAnonymous);
//ziskame token overeni systemu windows
Console.WriteLine("Token : {0}", identity.Token);

Použití deklarativního zabezpečení

Jistě si vzpomínáte, že v systému zabezpečení CAS bylo možné vyžadovat oprávnění jak standardním voláním metod na specifických typech (imperativní), tak pomocí specializovaných atributů (deklarativní). Podobně lze i v systému zabezpečení založeného na rolích využít atributů k realizaci deklarativní kontroly.

Za tímto účelem se nabízí k použití třída atributu PrincipalPermission, která stejně jako v případě deklarativního zabezpečení v CAS používá výčet SecurityAction spolu s dalšími parametry. Důležité je upozornit na skutečnost, že z výčtu SecurityAction mají efekt pouze hodnoty Demand, LinkDemand a InheritanceDemand. Ostatní hodnoty u tohoto typu atributu nefungují.

public class DeclarativePrincipalPermission
{
    public static void UseMethods()
    {
        try
        {
            //pokud neni aktualni uzivatel clenem role Administrators
            //bude vyhozena bezpecnostni vyjimka
            MethodForAdministrators();
            //pokud neni aktualni uzivatel Bob
            //bude vyhozena bezpecnostni vyjimka
            MethodForBob();
        }
        catch (SecurityException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
       
    [PrincipalPermission(SecurityAction.Demand, Role="Administrator")]
    public static void MethodForAdministrators()
    {
        string name = Thread.CurrentPrincipal.Identity.Name;
        Console.WriteLine("Uzivatel {0} je clenem skupiny Administrators", name);
    }

    [PrincipalPermission(SecurityAction.Demand, Name = "PC\\Bob")]
    public static void MethodForBob()
    {
        Console.WriteLine("Aktualni uzivatel je Bob");
    }
}

Jak z uvedeného příkladu můžeme vidět, tak je možné deklarativně omezovat vykonání metody v závislosti na roli, ale i na jménu aktuálního uživatele.

Příklady ke článku naleznete zde.

Témata článku: Software, Microsoft, Programování, Bezpečnost, Token, Walking, Catch

7 komentářů

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 14:04:24
    Pokud mate na mysli pridani zdrojaku v zipu do offline verze, tak tam jsou...
  • worker 29. 1. 2007 13:44:09
    hladam .net koderov na juniorske pozicie (BA) CV na dotnet.praca@gmail.com
  • Roman 25. 11. 2006 8:44:11
    Dobrý den, budete ještě pokračovat v seriálu C#?
    Děkuji
Určitě si přečtěte

Pojďme programovat elektroniku: Postavíme si titěrnou Wi-Fi meteostanici s lepším teploměrem než Netatmo

Pojďme programovat elektroniku: Postavíme si titěrnou Wi-Fi meteostanici s lepším teploměrem než Netatmo

** Dnes se podíváme na maličkou Wi-Fi destičku Wemos D1 mini ** A připojíme k ní barometrický a teplotní shield ** Poběží na ní web a nabídne i JSON API

18.  6.  2017 | Jakub Čížek | 27

Jak vybrat monitor k počítači: nenechte se zlákat nepodstatnými parametry

Jak vybrat monitor k počítači: nenechte se zlákat nepodstatnými parametry

** Na jaké parametry se zaměřit a kde vás výrobci chtějí nachytat ** Monitory se stále více specifikují pro konkrétní určení ** Náročný hráč nebo profesionální grafik mají různé požadavky

20.  6.  2017 | Tomáš Holčík | 28

Dlouhodobý test HTC Vive: co vám recenze o virtuální realitě neřeknou

Dlouhodobý test HTC Vive: co vám recenze o virtuální realitě neřeknou

** Ani hry se sebelepší grafikou vás nevtáhnou tolik, jako ve virtuální realitě ** Pro sledování filmů není VR ani zdaleka ideální ** I první generace je skvělá, stále však působí jako prototyp

20.  6.  2017 | Stanislav Janů | 19


Aktuální číslo časopisu Computer

Bojujeme proti Fake News

Dva velké testy: fotoaparáty a NASy

Co musíte vědět o změně evropského roamingu

Radíme s výběrem základní desky