Implementando uma permissão personalizada
Todos os objetos de permissão devem implementar a IPermission interface. Herdam o CodeAccessPermission classe é a maneira mais fácil de criar uma permissão personalizada, pois CodeAccessPermission implementa IPermission e fornece a maioria dos métodos necessários para uma permissão. Além disso, você deve implementar a IUnrestrictedPermission interface para todas as permissões de acesso de código personalizado. A classe de permissão personalizada é necessária para suporte tanto segurança imperativas e declarativas, portanto, você deve criá-la, mesmo se você planeja usar a segurança declarativa somente.
Observação
A permissão personalizada deve ser definida em um assembly diferente, por exemplo, o assembly no qual ela é referenciada.Se a permissão personalizada inclui um atributo de segurança para a segurança declarativa, a permissão personalizada e o atributo devem ser definidos em um assembly separado.Isso ocorre porque o atributo de segurança é executado quando o assembly foi carregado e o atributo não pode ter sido criado no momento em que a referência é encontrada.Tentando usar uma permissão declarativa no mesmo assembly no qual ele está definido resulta em um TypeLoadException que está sendo lançada.
Definição da classe de permissão
Para derivar a partir de CodeAccessPermission classe, você deve substituir os seguintes cinco métodos de chave e fornecer sua própria implementação:
Copycria uma duplicata do objeto de permissão atual.
IntersectRetorna a interseção das permissões concedidas da classe atual e uma classe passada.
IsSubsetOfRetorna true se uma permissão passada inclui tudo permitidas pela permissão atual.
FromXmlDecodifica uma representação XML da sua permissão personalizada.
ToXmlcodifica uma representação XML da sua permissão personalizada.
Unioncria uma permissão que é a união da permissão atual e a permissão especificada.
O IUnrestrictedPermission interface requer que você substituir e implementar um único método chamado IsUnrestrictedPermission. Para oferecer suporte a IUnrestrictedPermission interface, você deve implementar algum sistema, como, por exemplo, um valor booleano que representa o estado de restrição no objeto atual, para definir se a instância atual da permissão é irrestrita.
O fragmento de código a seguir ilustra a maneira na qual uma classe de permissão personalizada pode ser definida. Um construtor que aceita um PermissionState enumeração e um valor booleano chamado unrestricted são criado. O PermissionState enumeração tem um valor tanto da Irrestrito ou Nenhum. Se a enumeração passada tem um valor de Irrestrito, os conjuntos de construtor unrestricted para true. Caso contrário, unrestricted for definido como false. Além de para construtores específicos para a sua permissão personalizada, todas as permissões de acesso de código (qualquer permissão que herda de CodeAccessPermission) deve suportar um construtor que leva apenas um PermissionState enumeração.
Além para o código mostrado no exemplo a seguir, você deve implementar IsUnrestricted método e a substituição de Copy, Intersect, IsSubsetOf, ToXML, e FromXML métodos. Para obter informações sobre como concluir essas etapas, consulte as seções a seguir o exemplo.
Option Strict
Option Explicit
Imports System
Imports System.Security
Imports System.Security.Permissions
<SerializableAttribute()> NotInheritable Public Class CustomPermission
Inherits CodeAccessPermission
Implements IUnrestrictedPermission
Private unrestricted As Boolean
Public Sub New(state As PermissionState)
If state = PermissionState.Unrestricted Then
unrestricted = True
Else
unrestricted = False
End If
End Sub
'Define the rest of your custom permission here. You must
'implement IsUnrestricted and override the Copy, Intersect,
'IsSubsetOf, ToXML, and FromXML methods.
End Class
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.
}
Observe que a classe é marcada com SerializableAttribute. Você deve marcar a sua classe com SerializableAttribute para oferecer suporte a sintaxe declarativa usando um atributo. Para obter informações sobre como criar um atributo personalizado que usa um objeto de segurança personalizado, consulte Adicionando suporte de segurança declarativa.
Implementando o método IsUnrestricted
O IsUnrestricted método é necessária para o IUnrestrictedPermission interface e simplesmente retorna um valor booleano que indica se a instância atual da permissão tem acesso irrestrito ao recurso protegido pela permissão. Para implementar esse método, basta retornar o valor de unrestricted.
O seguinte código exemplo implementa o IsUnrestricted método.
Public Function IsUnrestricted() As Boolean Implements IUnrestrictedPermission.IsUnrestricted
Return unrestricted
End Function
public bool IsUnrestricted()
{
return unrestricted;
}
Substituindo o método de cópia
O método de cópia é necessária para o CodeAccessPermission de classe e retorna uma cópia da classe de permissão atual.
O código a seguir ilustra como substituir o Copy método.
Public Overrides Function Copy() As IPermission
Dim myCopy As New CustomPermission(PermissionState.None)
If Me.IsUnrestricted() Then
myCopy.unrestricted = True
Else
myCopy.unrestricted = False
End If
Return myCopy
End Function
public override IPermission Copy()
{
CustomPermission copy = new CustomPermission(PermissionState.None);
if(this.IsUnrestricted())
{
copy.unrestricted = true;
}
else
{
copy.unrestricted = false;
}
return copy;
}
Substituindo os métodos de IsSubsetOf e de interseção
Todas as permissões devem implementar a Intersect e IsSubsetOf métodos. O comportamento dessas operações deve ser implementado da seguinte maneira:
X.IsSubSetOf(Y) é true se a permissão y inclui tudo permitido pelo X.
X.Intersect(Y) resulta em uma permissão que permite que todas as operações e somente as operações permitidas pelas permissões de x e Y.
O exemplo a seguir ilustra como substituir e implementar a Intersect método. O método aceita uma classe que deriva de IPermission e inicializa essa uma nova instância da classe de CustomPermisison objeto. Nesse caso, a interseção do objeto atual e o objeto passado é um objeto final com o valor da irrestrita, se ambos os objetos possuem esse valor. No entanto, se um dos dois objetos possui um false valor para irrestrito, então o objeto final também terá uma false valor de irrestrito. Esse código retorna um objeto de irrestrito, somente se os dois objetos são irrestritos.
Public Overrides Function Intersect(target As IPermission) As IPermission
If Nothing Is target Then
Return Nothing
End If
Try
Dim PassedPermission As CustomPermission = CType(target, CustomPermission)
If Not PassedPermission.IsUnrestricted() Then
Return PassedPermission
End If
Return Me.Copy()
Catch InvalidCastException As Exception
Throw New ArgumentException("Argument_WrongType", Me.GetType().FullName)
End Try
End Function
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);
}
}
No exemplo a seguir, o IsSubsetOf método é substituído. Para que esse método retornar true, a instância atual e uma instância passada devem permitir que o mesmo conjunto de operações. Nesse caso, o método substituído inicializa uma nova instância do CustomPermission o objeto para o objeto de permissão do passado. Se o unrestricted valores são iguais e, em seguida, o método retorna true. Se não estiverem, o método retorna false.
Public Overrides Function IsSubsetOf(target As IPermission) As Boolean
If Nothing Is target Then
Return Not Me.unrestricted
End If
Try
Dim passedpermission As CustomPermission = CType(target, CustomPermission)
If Me.unrestricted = passedpermission.unrestricted Then
Return True
Else
Return False
End If
Catch InvalidCastException As Exception
Throw New ArgumentException("Argument_WrongType", Me.GetType().FullName)
End Try
End Function
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);
}
}
Substituindo os métodos de FromXml e ToXml
Permissões de suportam a XML para que um objeto de permissão pode ser salvo como XML e, em seguida, outro objeto de permissão podem ser restaurados para o valor do original de codificação, usando o arquivo XML. Para oferecer suporte a codificação XML, sua permissão personalizada deve implementar a ISecurityEncodable interface, que define um ToXml e um FromXml método. Porque os dois métodos são implementados por CodeAccessPermission, se sua classe de permissão personalizada derivada de CodeAccessPermission, você deve substituir esses métodos.
O conteúdo do elemento XML que representa o estado do objeto é determinado pelo próprio objeto. O FromXML método pode usar qualquer representação XML, desde que ToXML pode interpretá-lo e restaurar o estado do mesmo. No entanto, o que contém permissão elemento deve ser de um formulário padrão. Por exemplo, o formulário para CustomPermission pode parecer com o seguinte:
<IPermission class="CustomPermissions.CustomPermission, CustomPermissionAssembly " version="1" Unrestricted="True">
O IPermission elemento contém três atributos:
classe: Contém a ambigüidade removido pelo nome do assembly que contém o nome do tipo.
versão: Especifica a versão do XML de codificação (e não a versão do assembly da classe).
Irrestrito: Especifica se a permissão tem direitos irrestritos.
Todas as permissões devem ser codificadas em um elemento XML chamado IPermission para ser usado pelo sistema de segurança de tempo de execução de linguagem comum.
Novas versões de um objeto de permissão devem permanecer com versões anteriores compatíveis com informações persistentes no XML de versões anteriores. A marca de versão fornece informações para um objeto de permissão sobre qual versão codificados originalmente os dados.
O SecurityElement classe encapsula a funcionalidade principal que você precisa para criar e interagir com objetos de permissão codificados em XML. No entanto, porque o modelo de objeto XML usado para.NET Framework security é diferente de outros modelos de objeto XML, o SecurityElement classe não deve ser usado para gerar outros tipos de arquivos XML. Consulte a descrição da SecurityElement a classe para obter uma lista completa de seus membros.
O fragmento de código a seguir cria um XML permissão elemento:
Public Overrides Function ToXml() As SecurityElement
Dim element As New SecurityElement("IPermission")
Dim type As Type = Me.GetType()
Dim AssemblyName As New StringBuilder(type.Assembly.ToString())
AssemblyName.Replace(ControlChars.Quote, "'"c)
element.AddAttribute("class", type.FullName & ", " & AssemblyName.ToString)
element.AddAttribute("version", "1")
element.AddAttribute("Unrestricted", unrestricted.ToString())
Return element
End Function
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;
}
Observe que o exemplo anterior usa o StringBuilder.Replace método. Atributos na SecurityElement classe não pode conter aspas duplas, mas algumas informações de nome de assembly são aspas duplas. Para lidar com essa situação, o Substituir método converte aspas duplas (") no nome do assembly para aspas simples (').
O método a seguir lê um SecurityElement objeto criado pelo método anterior e define o valor atual da Irrestrito propriedade para aquele especificado pelo objeto passado. Esse método deve garantir que todas as informações armazenadas pelo ToXml método é recuperado.
Public Overrides Sub FromXml(PassedElement As SecurityElement)
Dim element As String = PassedElement.Attribute("Unrestricted")
If Not element Is Nothing Then
Me.unrestricted = Convert.ToBoolean(element)
End If
End Sub
public override void FromXml(SecurityElement PassedElement)
{
string element = PassedElement.Attribute("Unrestricted");
if(null != element)
{
this.unrestricted = Convert.ToBoolean(element);
}
}
Exemplo de permissão personalizada
O exemplo de código a seguir mostra uma classe inteira de permissão personalizada:
Option Explicit
Option Strict
Imports System
Imports System.Text
Imports System.Security
Imports System.Security.Permissions
Imports Microsoft.VisualBasic
<Serializable()>NotInheritable Public Class CustomPermission
Inherits CodeAccessPermission
Implements IUnrestrictedPermission
Private unrestricted As Boolean
Public Sub New(state As PermissionState)
If state = PermissionState.Unrestricted Then
unrestricted = True
Else
unrestricted = False
End If
End Sub
Public Function IsUnrestricted() As Boolean Implements IUnrestrictedPermission.IsUnrestricted
Return unrestricted
End Function
Public Overrides Function Copy() As IPermission
'Create a new instance of CustomPermission with the current
'value of unrestricted.
Dim myCopy As New CustomPermission(PermissionState.None)
If Me.IsUnrestricted() Then
myCopy.unrestricted = True
Else
myCopy.unrestricted = False
End If
'Return the copy.
Return copy
End Function
Public Overrides Function Intersect(target As IPermission) As IPermission
'If nothing was passed, return null.
If Nothing Is target Then
Return Nothing
End If
Try
'Create a new instance of CustomPermission from the passed object.
Dim PassedPermission As CustomPermission = CType(target, CustomPermission)
'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 Not PassedPermission.unrestricted Then
Return target
End If
'Return a copy of the current class if the passed one has
'an unrestricted value of true.
Return Me.Copy()
'Catch an InvalidCastException.
'Throw ArgumentException to notify the user.
Catch InvalidCastException As Exception
Throw New ArgumentException("Argument_WrongType", Me.GetType().FullName)
End Try
End Function
Public Overrides Function IsSubsetOf(target As IPermission) As Boolean
'If nothing was passed and unrestricted is false,
' return true.
If Nothing Is target Then
Return Not Me.unrestricted
End If
Try
'Create a new instance of CustomPermission from the passed object.
Dim passedpermission As CustomPermission = CType(target, CustomPermission)
'If unrestricted has the same value in both objects, then
'one is the subset of the other.
If Me.unrestricted = passedpermission.unrestricted Then
Return True
Else
Return False
End If
'Catch an InvalidCastException.
'Throw ArgumentException to notify the user.
Catch InvalidCastException As Exception
Throw New ArgumentException("Argument_WrongType", Me.GetType().FullName)
End Try
End Function
Public Overrides Sub FromXml(PassedElement As SecurityElement)
'Get the unrestricted value from the XML and initialize
'the current instance of unrestricted to that value.
Dim element As String = PassedElement.Attribute("Unrestricted")
If Not element Is Nothing Then
Me.unrestricted = Convert.ToBoolean(element)
End If
End Sub
Public Overrides Function ToXml() As SecurityElement
'Encode the current permission to XML using the
'SecurityElement class.
Dim element As New SecurityElement("IPermission")
Dim type As Type = Me.GetType()
Dim AssemblyName As New StringBuilder(type.Assembly.ToString())
AssemblyName.Replace(ControlChars.Quote, "'"c)
element.AddAttribute("class", type.FullName & ", " & AssemblyName.ToString)
element.AddAttribute("version", "1")
element.AddAttribute("Unrestricted", unrestricted.ToString())
Return element
End Function
End 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;
}
}