Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All
Important This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here.

Implementing a Custom Permission 

All permission objects must implement the IPermission interface. Inheriting from the CodeAccessPermission class is the easiest way to create a custom permission because CodeAccessPermission implements IPermission and provides most of the methods required for a permission. Additionally, you must implement the IUnrestrictedPermission interface for all custom code access permissions. The custom permission class is required for both imperative and declarative security support, so you should create it even if you plan to use only declarative security.

Defining the Permission Class

To derive from the CodeAccessPermission class, you must override the following five key methods and provide your own implementation:

  • Copy creates a duplicate of the current permission object.

  • Intersect returns the intersection of allowed permissions of the current class and a passed class.

  • IsSubsetOf returns true if a passed permission includes everything allowed by the current permission.

  • FromXml decodes an XML representation of your custom permission.

  • ToXml encodes an XML representation of your custom permission.

  • Union creates a permission that is the union of the current permission and the specified permission.

The IUnrestrictedPermission interface requires you to override and implement a single method called IsUnrestrictedPermission. In order to support the IUnrestrictedPermission interface, you must implement some system, such as a Boolean value that represents the state of restriction in the current object, to define whether the current instance of the permission is unrestricted.

The following code fragment illustrates the manner in which a custom permission class might be defined. A constructor that accepts a PermissionState enumeration and a Boolean value called unrestricted are both created. The PermissionState enumeration has a value of either Unrestricted or None. If the passed enumeration has a value of Unrestricted, the constructor sets unrestricted to true. Otherwise, unrestricted is set to false. In addition to constructors specific to your custom permission, all code access permissions (any permission that inherits from CodeAccessPermission) must support a constructor that takes only a PermissionState enumeration.

In addition to the code shown in the following example, you must implement IsUnrestricted method and override the Copy, Intersect, IsSubsetOf, ToXML, and FromXML methods. For information about completing these steps, see the sections that follow the example.

using System;
using System.Security;
using System.Security.Permissions;

[SerializableAttribute()]
public sealed class CustomPermission: CodeAccessPermission, IUnrestrictedPermission
{  
   private bool unrestricted;

   public CustomPermission(PermissionState state)
   {
      if(state == PermissionState.Unrestricted)
      {
         unrestricted = true;
      }
      else
      {
         unrestricted = false;
      }
   }     

   //Define the rest of your custom permission here. You must 
   //implement IsUnrestricted and override the Copy, Intersect, 
   //IsSubsetOf, ToXML, and FromXML methods.
}

Notice that the class is marked with SerializableAttribute. You must mark your class with SerializableAttribute in order to support declarative syntax using an attribute. For information about creating a custom attribute that uses a custom security object, see Adding Declarative Security Support.

Implementing the IsUnrestricted Method

The IsUnrestricted method is required by the IUnrestrictedPermission interface and simply returns a Boolean value that indicates whether the current instance of the permission has unrestricted access to the resource protected by the permission. To implement this method, simply return the value of unrestricted.

The following code example implements the IsUnrestricted method.

public bool IsUnrestricted()
{
   return unrestricted;
}

Overriding the Copy Method

The copy method is required by the CodeAccessPermission class and returns a copy of the current permission class.

The following code illustrates how to override the Copy method.

public override IPermission Copy()
{
   CustomPermission copy = new CustomPermission(PermissionState.None);

   if(this.IsUnrestricted())
   {
      copy.unrestricted = true;
   }
   else
   {
      copy.unrestricted = false;
   }
   return copy;
} 

Overriding the Intersect and IsSubsetOf Methods

All permissions must implement the Intersect and IsSubsetOf methods. The behavior of these operations must be implemented as follows:

  • X.IsSubsetOf(Y) is true if permission Y includes everything allowed by X.

  • X.Intersect(Y) results in a permission that allows all operations and only those operations allowed by both the X and Y permissions.

The following example illustrates how to override and implement the Intersect method. The method accepts a class that derives from IPermission and initializes this class to a new instance of the CustomPermisison object. In this case, the intersection of the current object and the passed object is a final object with the value of unrestricted if both objects have that value. However, if one of the two objects has a false value for unrestricted, then the final object will also have a false value for unrestricted. This code returns an unrestricted object only if both objects are unrestricted.

public override IPermission Intersect(IPermission target)
{
   try
   {
      if(null == target)
      {
         return null;
      }
      CustomPermission PassedPermission = (CustomPermission)target;

      if(!PassedPermission.IsUnrestricted())
      {
         return PassedPermission;
      }
      return this.Copy();
   }
   catch (InvalidCastException)
   {
      throw new ArgumentException("Argument_WrongType", this.GetType().FullName);
   }                
}

In the following example, the IsSubsetOf method is overridden. In order for this method to return true, the current instance and a passed instance must allow exactly the same set of operations. In this case, the overridden method initializes a new instance of the CustomPermission object to the passed permission object. If the unrestricted values are the same, then the method returns true. If they are not, the method returns false.

public override bool IsSubsetOf(IPermission target)
{  
   if(null == target)
   {
      return !this.unrestricted;
   }
   try
   {        
      CustomPermission passedpermission = (CustomPermission)target;
      if(this.unrestricted == passedpermission.unrestricted)
      {
         return true;
      }
      else
      {
         return false;
      }
   }
   catch (InvalidCastException)
   {
      throw new ArgumentException("Argument_WrongType", this.GetType().FullName);
   }                
}

Overriding the ToXml and FromXml Methods

Permissions support XML encoding so that a permission object can be saved as XML and then another permission object can be restored to the value of the original, using the XML file. To support XML encoding, your custom permission must implement the ISecurityEncodable interface, which defines a ToXml and a FromXml method. Because both methods are implemented by CodeAccessPermission, if your custom permission class derives from CodeAccessPermission, you should override these methods.

The content of the XML element that represents the object state is determined by the object itself. The FromXML method can use any XML representation as long as ToXML can interpret it and restore the same state. However, the containing Permission element must be of a standard form. For example, the form for CustomPermission might look like the following:

<IPermission class="CustomPermissions.CustomPermission, CustomPermissionAssembly " version="1" Unrestricted="True">

The IPermission element contains three attributes:

  • class: Contains the type name disambiguated by the name of the assembly that contains it.

  • version: Specifies the version of the XML encoding (not the version of the class's assembly).

  • Unrestricted: Specifies whether the permission has unrestricted rights.

All permissions must be encoded in an XML element called IPermission in order to be used by the common language runtime security system.

New versions of a permission object should remain backward compatible with information persisted in XML from previous versions. The version tag provides information to a permission object about which version originally encoded the data.

The SecurityElement class encapsulates the main functionality that you need in order to create and interact with XML-encoded permission objects. However, because the XML object model used for .NET Framework security is different from other XML object models, the SecurityElement class should not be used to generate other types of XML files. See the description of the SecurityElement class for a complete list of its members.

The following code fragment creates an XML Permission element:

public override SecurityElement ToXml()
{
   SecurityElement element = new SecurityElement("IPermission");
   Type type = this.GetType();
   StringBuilder AssemblyName = new StringBuilder(type.Assembly.ToString());
   AssemblyName.Replace('\"', '\'');
   element.AddAttribute("class", type.FullName + ", " + AssemblyName);
   element.AddAttribute("version", "1");
   element.AddAttribute("Unrestricted", unrestricted.ToString());
   return element;
}

Notice that the previous example uses the StringBuilder.Replace method. Attributes in the SecurityElement class cannot contain double quotes, but some assembly name information is in double quotes. To handle this situation, the Replace method converts double quotes (") in the assembly name to single quotes (').

The following method reads a SecurityElement object created by the previous method and sets the current value of the Unrestricted property to the one specified by the passed object. This method should ensure that any information stored by the ToXml method is retrieved.

public override void FromXml(SecurityElement PassedElement)
{
   string element = PassedElement.Attribute("Unrestricted");
   if(null != element)
   {  
      this.unrestricted = Convert.ToBoolean(element);
   }
}

Custom Permission Example

The following code example shows an entire custom permission class:

using System;
using System.Text;
using System.Security;
using System.Security.Permissions;

[Serializable()]
public sealed class CustomPermission: CodeAccessPermission , IUnrestrictedPermission
{
   private bool unrestricted;

   public CustomPermission(PermissionState state)
   {
      if(state == PermissionState.Unrestricted)
      {
         unrestricted = true;
      }
      else
      {
         unrestricted = false;
      }
   }
      
   public bool IsUnrestricted()
   {
      return unrestricted;
   }

   public override IPermission Copy()
   {
      //Create a new instance of CustomPermission with the current
      //value of unrestricted.
      CustomPermission copy = new CustomPermission(PermissionState.None);

      if(this.IsUnrestricted())
      {
         copy.unrestricted = true;
      }
      else
      {
         copy.unrestricted = false;
      }
      //Return the copy.
      return copy;
   }

   public override IPermission Intersect(IPermission target)
   {
      //If nothing was passed, return null.
      if(null == target)
      {
         return null;
      }
      try
      {
         //Create a new instance of CustomPermission from the passed object.
         CustomPermission PassedPermission = (CustomPermission)target;

         //If one class has an unrestricted value of false, then the
         //intersection will have an unrestricted value of false.
         //Return the passed class with the unrestricted value of false.
         if(!PassedPermission.unrestricted)
         {
            return target;
         }
         //Return a copy of the current class if the passed one has
         //an unrestricted value of true.
         return this.Copy();
      }
      //Catch an InvalidCastException.
      //Throw ArgumentException to notify the user.
      catch (InvalidCastException)
      {
         throw new ArgumentException("Argument_WrongType", this.GetType().FullName);
      }                
   }

   public override bool IsSubsetOf(IPermission target)
   {
      //If nothing was passed and unrestricted is false,
      //then return true. 
      if(null == target)
      {
         return !this.unrestricted;
      }
       try
      {        
         //Create a new instance of CustomPermission from the passed object.
         CustomPermission passedpermission = (CustomPermission)target;

         //If unrestricted has the same value in both objects, then
         //one is the subset of the other.
         if(this.unrestricted == passedpermission.unrestricted)
         {
            return true;
         }
         else
         {
            return false;
         } 
      }
      //Catch an InvalidCastException.
      //Throw ArgumentException to notify the user.
      catch (InvalidCastException)
      {
         throw new ArgumentException("Argument_WrongType", this.GetType().FullName);
      }                    
   }

   public override void FromXml(SecurityElement PassedElement)
   {
      //Get the unrestricted value from the XML and initialize 
      //the current instance of unrestricted to that value.
      string element = PassedElement.Attribute("Unrestricted");         
 
      if(null != element)
      {  
         this.unrestricted = Convert.ToBoolean(element);
      }
   }

   public override SecurityElement ToXml()
   {
      //Encode the current permission to XML using the 
      //SecurityElement class.
      SecurityElement element = new SecurityElement("IPermission");
      Type type = this.GetType();
      StringBuilder AssemblyName = new StringBuilder(type.Assembly.ToString());
      AssemblyName.Replace('\"', '\'');
      element.AddAttribute("class", type.FullName + ", " + AssemblyName);
      element.AddAttribute("version", "1");
      element.AddAttribute("Unrestricted", unrestricted.ToString());
      return element;
   }
}

See Also

Community Additions

ADD
Show:
© 2015 Microsoft