Hoofdstuk 12 - Les 1

Authentication = identiteit van de gebruiker vaststellen
Authorization = De rechten van een gebruiker verifiëren voor toegang tot een resource.

System.Principal.WindowsIdentity representeert een Windows gebruiker. Authenticeert niet, dat heeft Windows al gedaan. Deze class houd de gebruikersnaam, authenticatie type en account token bij.
Als een instantie wordt gemaakt wordt van de WindowsIdentity class kan gebruik worden gemaakt van drie static methoden:
  1. GetAnonymous – Returnt een WindowsIdentity object die een anonieme ongeauthentiseerde gebruiker representeert.
  2. GetCurrent – Returnt een WindowsIdentity object die de huidige ingelogde Windows gebruiker representeert.
  3. Impersonate – Returnt een WindowsImpersonationContext die een gespecificeerde gebruiker representeert.

WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();


De System.Security.Principal.WindowsPrincipal class biedt toegang tot een gebruikers zijn groep lidmaatschap. Een object van deze class moet aangemaakt worden door een WindowsIdentity class:
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal currentPrincipal = new WindowsPrincipal(currentIdentity);
De WindowsPrincipal class kan worden gebruikt om vast te stellen van welke groepen een gebruiker lid is. Om te kijken of een gebruiker lid is van een built-in groep gebruik daarvoor de WindowsPrinicipal.IsInRole methode en geef als parameter een object van System.Security.Principal.WindowsBuiltInRole mee:
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal currentPrincipal = new WindowsPrincipal(currentIdentity);
If(currentPrincipal.IsInRole(WindowsBuiltInRole.Administrator)
// Do something
if(currentPrincipal.IsInRole(WindowsBuiltInRole.PowerUser)
// Do something
if(currentPrincipal.IsInRole(WindowsBuiltInRole.User)
// Do something

Ook kan gecheckt worden of een gebruiker in een zelfgemaakte groep zit, door gebruik te maken van de IsInRole method met als parameter de naam van de groep met als type string:
If(currentPrincipal.IsInRole(@”Domein\MijnGroep”)
// Do something


De System.Security.Permissions.PrincipalPermission class en de gerelateerde PrincipalPermissionAttribute class checken de actieve principal voor zowel declarative en imperative beveiligings acties. Zij eisen date de gebruiker geauthenticeerd is of dat zij behoren tot een groep. De PrincipalPermission kent drie properties die gecombineerd met elkaar kunnen worden:
  1. Authenticated – Een boolean. Indien true, de gebruiker moet permissions hebben.
  2. Name – Een string die de identiteit van de gebruiker moet matchen.
  3. Role – Een string die overeen moet komen met een van de prinicipal’s rollen.


De PrincipalPermission.Demand methode gaat na (aan de hand van de bovenstaande opgegeven properties, geen van hen mag null zijn) of de gebruiker toegang heeft tot de opgevraagde resource. Zo niet, dan gooit de methode een exceptie.

TipPrincipalPermission kent geen andere properties dan diegene die zojuist zijn beschreven!

Declaratieve RBS demands instrueren de runtime een check uit te voeren voordat een method wordt uitgevoerd. Dit is de meest veilige manier om RBS te gebruiken om toegang te bieden tot een resource. Twee nadelen:
  1. Ze kunnen alleen worden gebruikt om toegang te verbieden tot methods
  2. Runtime kan een exception worden gegooid. Als de methode wordt aangeroepen door een Windows event, dan vangt Windows de exception op en de applicatie stopt met uitvoeren.

Om gebruik te maken van declaratieve demands moeten drie elementen in de code aanwezig zijn:
  1. De System.AppDomain.CurrentDomain.SetPrincipalPolicy methode om de principal security policy te specificeren.
  2. Een try/catch block om ongeauthoriseerde toegangen op te vangen.
  3. Een PrincipalPermission attribuut om de toegang van een methode te bepalen.

Twee dingen moeten nog worden gedefinieerd als gebruik gemaakt wordt van PrincipalPermission:
  1. De actie die PrincipalPermission moet uitvoeren. Gebruik hiervoor de System.Security.Permissions.SecurityAction enumeratie. SecurityAction.Demand voor declaratieve RBS.
  2. Een of meerdere PrincipalPermission properties. Gebruik Authenticated om toegang te bieden tot enkel geauthenticeerde gebruikers. Role om toegang te bieden op groepsniveau en User om toegang te bieden voor specifieke gebruikers.

[PrincipalPermission(SecurityAction.Demand, Role=@”BUILTIN\Administrators”)]
static void AdministratorsOnlyMethod()
{
// code dat enkel kan worden uitgevoerd door administrators
}

Ook kan gebruik gemaakt worden van meerdere declaratieve eisen. Als de gebruiker aan een van de eisen voldoet verkrijgt deze toegang:

[PrincipalPermission(SecurityAction.Demand, Name=@”Domain\Administrator”)]
[PrincipalPermission(SecurityAction.Demand, Name=@”Domain\User1”, Role=@”Domain\Managers”)]
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
static void AdministratorsOnlyMethod()
{
// Code dat enkel door bovengenoemde gebruikers kan worden uitgevoerd
}
Imperatieve RBS eisen worden gedeclareerd in code en kunnen worden gebruikt om gedeeltes van code te beveiligen op een meer specifieke basis dan declaratieve RBS eisen. Ofterwel: gebruik imperatief om gedeeltes van een methode te begrenzen en gebruik declaratief om de gehele methode te begrenzen. Vier onderdelen zijn nodig voor imperatief gebruik:
  1. De System.AppDomain.CurrentDomain.SetPrincipalPolicy methode om de principal security policy to specificeren.
  2. Een try/catch block om de niet geauthoriseerde aanvragen af te vangen en error reporting.
  3. Een PrincipalPermission object waarvan de properties gezet zijn voor de begrenzing.
  4. Een aanroep naar de PrincipalPermission.Demand methode om de methode zijn toegang te declareren.
De eerste 2 elementen gelden ook voor declaratieve RBS toegang en moeten op dezelfde wijze worden geïmplementeerd.Het gebruik van de PrincipalPermission class is anders. Deze class kent drie overloading constructors:
  1. PrincipalPermission(PermissionState) – Specificeer de PrincipalPermission object properties door gebruik te maken van het System.Security.Permissions.PermissionState object.
  2. PrincipalPermission(Name, Role) – Specificeer de naam en rol properties. Indien gebruikersnaam voldoende is, vul dan null voor role.
  3. PrincipalPermission(Name, Role, Authenticated) – Specificeer de propertie waarden. Gebruik null als een toegangsmogelijkheid niet gebruikt hoeft te worden.
De volgende code gooit een exception als de gebruiker niet tot de administrators groep behoort.
// Definieer de security policy: Windows security
System.AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
// Stel groep(role) samen
string r = System.Environment.MachineName + @ “\VS Developers”;
Try
{
PrincipalPermission p = new PrincipalPermission(null, r, true);
p.Demand();
// doe nog wat code, de gebruiker heeft toegang
}
catch(System.Security.SecurityException ex)
{
// TODO: error log
}
Om gebruikers te authentificeren die opgeslagen zijn in een database kan gebruik gemaakt worden van de System.Security.Principal.IIdentity en System.Security.IPrincipal interface. Daarnaast kan de class worden uitgebreid met additionele properties en methods.
De IIdentity interface is een template voor het maken van identity classes. De WindowsIdentity class is een implementatie van IIDentity. Ditzelfde geldt ook voor FormsIdentity en PassportIdentity voor web authenticatie.
De volgende properties moeten worden geïmplementeerd als de IIdentity interface wordt gebruikt:
  • AuthenticationType – Een string die gebruikt wordt om een omschrijving op te slaan van de gebruiker zijn authentication machanisme. Applicaties kunnen deze property gebruiken om te bepalen of de authenticatie mechanisme kan worden vertrouwd. De ene applicatie neemt genoegen met Passport authenticatie, de andere niet. Specificeer hier een unieke AuthenticationType.
  • IsAuthenticated – Een bool die op true moet staan als de gebruiker is geauthenticeerd.
  • Name – Een string die de gebruikersnaam bevat. Deze porperty moet bestaan, zelfs als het authentification mechanisme geen gebruikersnaam gebruikt. Het op een unieke manier de gebruiker identificeren; maar 1 account kan een bepaalde naam dragen.
Ook dient de constructor geïmplementeerd te worden die de (bovenstaande) properties zet.

Net zoals de WindowsIdentity is gebaseerd op IIdentity, zo implementeren WindowsPrincipal en GenericPrincipal de IPrincipal interface. Objecten gebaseerd op deze interface representeren de security context van een gebruiker, inclusief de identiteit van de gebruiker en de rollen of groepen waarin de gebruiker behoort.
Om IPrincipal te implementeren moet minstens 1 constructor, 1 porperty en 1 methode zijn geïmplementeerd. De constructor moet een IIdentity object accepteren en een string array van identity roles. Er kunnen wel meerdere constructors geïmplementeerd worden. De property die moet worden geimplementeerd is IPrincipal.Identity. De methode is de IPrincipal.IsInRole methode welke een bool returnt en een string accepteert als parameter.

Als je geen gebruik wil maken van IIdentity of IPrincipal en je heb enkel de basis functionaliteit nodig, gebruik dan System.Security.Principal.GenericIdentity en System.Security.Principal.GenericPrincipal. Deze classes bieden enkel de properties en methoden aan die nodig zijn vanwege de interfaces.
GenericIdentity heeft 2 overloaded constructors. De waarden die meegegeven worden aan de constructor kunnen later niet meer worden aangepast.
GenericIdentity user = new GenericIdentity(“Tomas”);
GenericIdentity user2 = new GenericIdentity(“Tomas”, “SmartCard”);
GenericPrincipal heeft 1 constructor die zowel een GeneriIdentity object nodig heeft als een string array met rollen.
String[] userRoles = new String[] {"IT","Users","Administrators"};
GenericPrincipal p = new GenericPrincipal(user, userRoles);
De aanroep p.IsInRole("Users") zal true geven.

Of je nu gebruik maakt van de IIdentity en IPrincipal interface of van GenericPrincipal en GenericIdentity, je kan altijd nog gebruik maken van dezelfdedeclaratieve en imperatieve RBS technieken. Voer hiervoor de volgende stappen uit:
  • Maak een IIdentity of GenericIdentity object aan die de gebruiker voorstelt
  • Maak een Principal of GenericPrincipal object aan gebaseerd op het IIdentity object
  • Zet de Thread.CurrentPrincipal property naar het IPrincipal object
  • Voeg de benodigde declaratieve of imperateive RBS eisen toe

Static void Main(string[] args)
{
GenericIdentity user1 = new GenericIdentity("Tomas");
String[] roles1 = new String[] {"IT", "Users", "Administrators"};
GenericPrincipal p1 = new GenericPrincipal(user1, roles1);
GenericIdentity user2 = new GenericIdentity(“Miep”);
String[] roles2 = new String[] { "Users" };
GenericPrincipal p2 = new GenericPrincipal(user2, roles2);

Try
{
Thread.CurrentPrincipal = p1;
TestSecurity();
Thread.CurrentPrincipal = p2;
TestSecurity();
}
catch(Exception ex)
{
Console.WriteLine(ex.GetType().ToString() + " veroorzaakt door: " + Thread.CurrentPrincipal.Identity.Name);
}
}
[PrincipalPermission(SecurityAction.Demand, Role = "IT")]
private static void TestSecurity()
{
Console.WriteLine(Thread.CurrentPrincipal.Identity.Name + " is in rol IT");
}
Bovenstaande code geeft user1 het recht om de methode TestSecurity uit te voeren omdat deze in de rol IT zit. User2 geeft een exceptie omdat deze niet in de rol IT zit.

Reacties

Populaire posts van deze blog

[SQL Server] varchar vs nvarchar

MS Sql 70-461: Chapter 5

[C#] Class serialiseren en deserialiseren