To ensure that only callers that have been granted a specified permission can call your code, you can declaratively or imperatively demand that callers of your code have a specific permission or set of permissions. A demand causes the runtime to perform a security check to enforce restrictions on calling code. During a security check, the runtime walks the call stack, examining the permissions of each caller in the stack and determining whether the permission being demanded has been granted to each caller. If a caller that does not have the demanded permission is found, the security check fails and a SecurityException is thrown. The only demands that do not result in a stack walk are link demands, which check only the immediate caller.
You can cause a security check to take place every time a particular method is called or before a particular block of code is executed. If you want the security check to occur when any member of a particular class is called, you can place a demand before the class so that it applies to every member of the class. The remainder of this topic explains how you make security demands, when you should do so, and why you might choose one type of security demand over another.
If you are writing a library that directly accesses a protected resource and if this access is exposed to the caller, you must make a security demand in the library to help verify that all callers in the call stack have permission to access that resource. Your demands can be declarative or imperative. Note that demands should never be made in a class constructor because class constructor code is not guaranteed to execute at any particular point or in any particular context. Because the state of the call stack in a class constructor is not well defined, demands placed on class constructors can produce unexpected and undesired results.
You should use the following guidelines, regardless of the type of demand you make:
- Ensure that the caller originated from a particular site or zone, or was signed by a particular publisher, by demanding that callers have a particular identity permission. However, you should do this only when you are giving additional access based on matching an identity, not when you are denying access based on matching an identity. Because it is relatively simple to modify or mask code's identity, denying access based on identity alone is not a reliable way of protecting your code and the resources it accesses from unauthorized access.
- Ensure that an object can be created only by callers who have a specific permission by placing the demand on the class level of that object. For example, suppose you have a class called
myFileStream, which derives from the FileStream class, and you want to ensure that only authorized callers can create instances of
myFileStream. You would place a declarative demand for a FileIOPermission object that represents the right to access the stream created by
myFileStreamon the class level of the
- You can also put demands in code that set or get a property. In general, you put demands for less restrictive permissions on the get accessor rather than on the set accessor, unless the property holds sensitive information, such as a password.
Note Role-based security checks have slightly different semantics than code access security checks. For more information, see Role-Based Security.
Note Demands can be applied at the class, method, event, and property levels only; assemblies and individual non-private variable members are not protected by demands. Demands placed on the assembly or non-private variable level will not produce a compiler warning. Therefore, it is important to use properties instead of public members in order to insure the protection that demands provide.