Imperative security involves manually creating an instance of a permission within a method to protect the entire method using that permission and declarative security involves the use of code attributes. Declarative security also allows the CLR and other developers to interrogate an application's security needs even if it's not running by examining the security attributes using Reflection. When you apply a permission attribute to a method, the code within the method cannot be executed unless the stack-walk check performed by the CLR for the security permission evaluates to true. The code in Listing 14.4 illustrates the use of a code attribute in declarative security. You can follow the routine from the previous imperative samples to restrict the trust level of this code so that the permission demand will fail. Listing 14.4. Declarative Security
Refer to the list of permissions earlier in this chapter for the list of permission attributes that you can apply to methods and classes. Also note that you can apply the PrincipalPermission attribute to a method, effectively preventing anyone who does not pass the identity check from executing that method. The first edition of this book showed you how you can create code that will block unwanted callers from using your public classes by using the StrongNameIdentityPermissionAttribute class declaratively. The idea is that you restrict the list of potential callers to only those callers that have that public key. This works just fine in .NET 1.0 and .NET 1.1. However, in .NET 2.0, any fully trusted assembly will satisfy any demand, including link demands for strong name identity permissions. In other words, if you decorate your method with a StrongNameIdentityPermission attribute like the one in the following code, you will only be protecting yourself against partially trusted callers. [StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey = "0024000004800000940000000602000000240000525341310004000001000100D353D6DE2BE4BC" + "60048A198B5509CF4DF479CBD614EB9FBE3FCDF68937E711630B6F21FA2E7C153F319D213 42B1C8C" + "272647939816EEE90D011D8A17FDF6AA220B4C6F2043496277C1BC392EAD8F0BDEB9046 5A7EB9C47" + "0E1C699ECD1A8E83C670CD74440B0033D7D4C74F7F6C9392F83DCD95054A8DAA57 5390CFC1FCF586BF")] public class Class1 { public Class1() { } public string GetSecretWord() { return "SAMSPress"; } } If you try to access this code from another C# application that you created on your own hard drive, it would work just fine, completely allowing access to the GetSecretWord() method, because code you create on your own machine is fully trusted by default. If you really need to limit the access to your code, you can create an internal method, which will only be visible to code within your assembly, and then use the InternalsVisibleToAttribute class to indicate to what assembly you want to expose internal members and essentially create a "friend" assembly. The use of that attribute, however, is beyond the scope of this chapter. |