Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.
CAS może być używany deklaratywnie wtedy kod jest poddany kontroli bezpieczeństwa już na etapie kompilacji przed uruchomieniem kodu lub imperatywnie wtedy kod sam wykonuję kontrolę bezpieczeństwa i decyduje co ma się zdarzyć podczas niepowodzenia. W poprzedniej lekcji było pokazane jak chronić całe assembly. Ale można użyć również CAS do chronienia pojedynczej metody bądź wyodrębnionego kodu.
Typy metod Permission Requests
Mimo, że są trzy typy deklaracji CAS assembly ( RequestOptional, RequestMinimum, and RequestRefuse), dostępne są dodatkowo cztery opcje dla imperatywnych i deklaratywnych uprawnień w metodzie. Oto one:
Assert – zobowiązuje runtime do ignorowania tego, że wywołujący metodę mogą nie mieć odpowiednich uprawnień.
Demand – zobowiązuje runtime do wyrzucenia wyjątku jeśli wywołujący metodę są wyżej na stosie bez określonych uprawnień
Deny – powoduje usunięcie dostępu do pewnych ograniczeń
PermitOnly – powoduje usunięci wszystkich innych uprawnień oprócz aktualnie użytego
Są jeszcze dwie dodatkowe opcje dostępne tylko dla deklaratywnych metod ochrony:
LinkDemand- powoduje wywołanie wyjątku jeśli aktualna bezpośrednio wywołująca metoda jest wyżej na stosie
InheritanceDemand- zobowiązuje runtime do wyrzucenia wyjątku jeśli assambly dziedziczone z klasy nie ma odpowiednich uprawnień
W training kit jest ekstra historyjka która wyjaśnia nam te wszystkie opcje i powoduje, że stają się one w pełni do zrozumienia. Nie będę jej tutaj pisał bo to ponad połowa A4 ;)
Guidelines for Using Method Permission Requests
Jako programiści mamy do wyboru wiele rodzajów implementacji CAS w naszych aplikacjach. Wybór sposobu realizacji CAS w danej sytuacji może być trudny. Poniżej mini wskazówki:
- użyj SecurityAction.PermitOnly aby ograniczyć dostęp do uprawnień dla każdej metody
- użyj SecurityAction.Deny aby nadać pozwolenia dla każdej metody
- użyj CodeAccessPermission.PermitOnly do bezwzględnego ograniczenia uprawnień danej sekcji kodu w metodzie do ilości uprawnień całej metody. Jest to szczególnie ważne podczas wywoływania obiektów utworzonych przez osoby trzecie.
- użyj CodeAccessPermission.Assert kiedy chcemy aby część zaufanego kodu wywoła metodę która nie ma odpowiednich uprawnień.
- użyj CodeAccessPermission.Demand tylko wtedy kiedy assambly implementuje funkcje które nie należą bezpośrednio do .NET Framework
Techniques for Demanding Permissions
Dwa z wyliczeń SecurityAction powodują wyrzucenie wyjątku podczas gdy brakuje określonych uprawnień CAS, są to: Demand i LinkDemand. Różnica pomiędzy nimi jest taka, że Demand weryfikuje wszystkie metody natomiast LinkDemand nie weryfikuje metody bezpośrednio wywołującej inne. Będzie to zobrazowane dobrze na poniższych dwóch rysunkach. Jak zwykle ciężko pokusić się o kompromis…ze względu na to, że Demand sprawdza wszystkie metody wykonuje się po prostu wolniej natomiast LinkDemand- szybszy ale mniej bezpieczny.

How to Demand CAS Permissions Declaratively
Stworzenie metody CAS jest bardzo podobne do utworzenia assembly CAS. Musimy jednak używać innych wyliczeń z SecurityAction i samą deklaracje robimy jako atrybuty metody. W przykładzie poniżej będzie pokazane deklaracji dwóch metod FileIOPermissionAttribute i WebPermissionAttribute które deklaratywnie sprawdzą czy dana metoda ma dostęp do odpowiednich plików i storny MS.
1: // C#
2: [FileIOPermission(SecurityAction.Demand, Write = @"C:\Program Files\")]
3: public static void createProgramFolder()
4: {
5: // Method logic
6: }
7: [WebPermission(SecurityAction.Demand,
8: ConnectPattern = @"http://www\.microsoft\.com/.*")]
9: public static void requestWebPage()
10: {
11: // Method logic
12: }
How to Demand CAS Permissions Imperatively
Poniżej deklaracje metod które wykonują identyczne zadania lecz są weryfikowane imperatywnie. Jakich wyliczeń (czyli uprawnień) możemy używać imperatywnie podałem powyżej.
1: // C#
2: public static void createProgramFolder()
3: {
4: try
5: {
6: FileIOPermission filePermissions =
7: new FileIOPermission(FileIOPermissionAccess.Write, @"C:\Program Files\");
8: filePermissions.Demand();
9: // Method logic
10: }
11: catch
12: {
13: // Error-handling logic
14: }
15: }
16: public static void requestWebPage()
17: {
18: try
19: {
20: Regex connectPattern = new Regex(@"http://www\.microsoft\.com/.*");
21: WebPermission webPermissions =
22: new WebPermission(NetworkAccess.Connect, connectPattern);
23: webPermissions.Demand();
24: }
25: catch
26: {
27: // Error-handling logic
28: }
29: }
Jak widać tutaj zaletą imperatywnej kontroli jest to, że możemy ładnie obsłużyć wyrzucane wyjątki.
How to Analyze Granted Permissions
Jeśli chcemy sprawdzić czy assembly ma odpowiedni uprawnienia CAS nie możemy użyć Demand. Demand może sprawdzić metodę wywołującą ale nie same assembly. Jeżeli jednak zaistnieje taka potrzeba skorzystajmy z System.Security.SecurityManager.IsGranted. Przykład użycia:
1: // C#
2: FileIOPermission filePermissions = new
3: FileIOPermission(FileIOPermissionAccess.Read, @"C:\Windows\");
4: if ( SecurityManager.IsGranted(filePermissions) == true )
5: // Assembly can read the C:\Windows directory
6: else
7: // Assembly cannot read the C:\Windows directory
Techniki ograniczania uprawnień
Możesz kontrolować uprawnienia na bardziej szczegółowym poziomie, ograniczając uprawnienia dla poszczególnych metod przy użyciu deklaracji lub wywołując imperatywne oświadczenia. Dwa wyliczenia z SecurityAction powodują zmniejszenie uprawnień CAS – Deny i PermitOnly. Deny usuwa pojedyncze, bądź grupę uprawnień natomiast PermitOnly usuwa ograniczania poza aktualnie używanym.
How to Limit Method Permissions Declaratively
Poniżej przykład jak ograniczyć metodzie dostęp do folderu Windows i dostęp żądań wychodzących sieci web do storny MS.
1: // C#
2: [FileIOPermission(SecurityAction.Deny, ViewAndModify = @"C:\Windows\")]
3: [WebPermission(SecurityAction.PermitOnly,
4: ConnectPattern = @"http://www\.microsoft\.com/.*")]
How to Limit Permissions Imperatively
Przykład imperatywny robiący to samo co powyższy:
1: // C#
2: // Deny access to the Windows directory
3: FileIOPermission filePermissions =
4: new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:\Windows\");
5: filePermissions.Deny();
6: // Method logic
7: // Permit only Web access, and limit it to www.microsoft.com
8: Regex connectPattern = new Regex(@"http://www\.microsoft\.com/.*");
9: WebPermission webPermissions = new WebPermission(NetworkAccess.Connect,
10: connectPattern);
11: webPermissions.PermitOnly();
12: // Method logic
How to Relax Permissions and Potentially Improve Performance
Korzystanie z CAS pomaga w bezpieczeństwie ale tracimy oczywiście na wydajności. Wcześniej była mowa o LinkDemand ale tam traciliśmy na bezpieczeństwie o które nam chodzi. Tutaj z pomocą przychodzi nam metoda Assert. Permission objects zawiera metode Assert która ręczy za wszystkie metody wywołujące. Spójrzmy może na rysunek bo ciężko to wytłumaczyć ;)

Na dzisiaj tyle. Następne trzy artykuły również będą o bezpieczeństwie. Dzięki za poświęcenie czasu następny artykuł już w nowym roku ;)
Kolejny artykuł w serii to 70-536: Authenticating and Authorizing Users