Compartilhar via


Otimizações de segurança

Verificações de segurança podem causar problemas de desempenho para alguns aplicativos.Existem duas técnicas de otimização que você pode usar para melhorar o desempenho.Uma técnica que combina as exigências de segurança; o Outros suprime demandas de permissão para telefonar código não gerenciado.Embora essas técnicas podem melhorar o desempenho do seu aplicativo, eles podem tornar vulnerável a explorações de segurança do aplicativo.Antes de usar essas técnicas de otimização, você deve tomar as seguintes precauções:

  • Execute o Diretrizes para Codificação Segura para código gerenciado.

  • Compreender sistema autônomo implicações de segurança das otimizações e usar outros métodos para proteger seu aplicativo conforme apropriado.

  • Implemente as otimizações de segurança mínima necessárias para melhorar o desempenho do aplicativo.

Depois de otimizar seu código, você deve testar o código otimizado para determinar se seu desempenho, na verdade, aprimorado.Caso contrário, você deve remover as otimizações de segurança para ajudar a impedir falhas na segurança inadvertidas.

Cuidado:

Otimização de segurança requer que você altere a segurança de acesso do código padrão.Para evitar introduzir vulnerabilidades de segurança no seu código, certifique-se de que você entender as implicações de segurança das técnicas de otimização antes de usá-los.

A combinação de solicitações de segurança

Para otimizar o código que faz com que as exigências de segurança, você pode, em algumas situações, usar uma técnica para combinar as demandas.

Por exemplo, se:

  • o código realiza uma série de operações dentro de um único método, e

  • ao executar cada uma dessas operações, seu código chama uma biblioteca de classes gerenciadas que exige que seu código tenha a mesma permissão em cada telefonar para a biblioteca

em seguida:

  • Você pode modificar seu código para executar um Por solicitação and an Declarar essa permissão para reduzir a sobrecarga incorrida pelas solicitações de segurança.

Se o telefonar profundidade da pilha acima o método é grande, usar essa técnica pode resultar em um ganho de desempenho significativos.

Para ilustrar como isso funciona, suponha que o método M executa operações de 100.Cada operação chama uma biblioteca que faz uma demanda de segurança que exigem seu código e todos os chamadores ter a permissão de X.Por causa das solicitações de segurança, cada operação faz com que o tempo de execução percorrer toda a telefonar empilhar examinando cada telefonar er de permissões, para determinar se X permissão, na verdade, foi concedido a cada telefonar er.Se a pilha de chamadas acima método M é n níveis, 100n comparações são necessárias.

Para otimizar, você pode fazer o seguinte método M:

  • Demanda X, que resultados em tempo de execução realizar um exame da pilha (de profundidade n) para garantir que todos os chamadores realmente tenham permissão X.

  • Em seguida, declarar permissão X, que faz com que subseqüentes pilha walks parar no método M e bem-sucedido, assim reduzindo o número de comparações de permissão por 99 n.

No exemplo de código a seguir, a GetFileCreationTime método leva uma representação de seqüência de um diretório sistema autônomo um parâmetro e exibe a nome e data de criação de cada arquivo nesse diretório. O estáticoFile.GetCreationTime método lê informações de arquivos, mas requer que uma demanda e pilha orientá-lo para cada arquivo que ele lê. O método cria uma nova instância do FileIOPermission objeto, executa uma demanda para verificar as permissões de todos os chamadores na pilha e, em seguida, declara a permissão se a solicitação for bem-sucedida.Se a solicitação for bem-sucedida, apenas um pilha walk é executada e o método lê o time de criação de cada arquivo no diretório do passado.

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

namespace OptimizedSecurity
{
   public class FileUtil
   {
      public FileUtil()
      {
      }

      public void GetFileCreationTime(string Directory)
      {
         //Initialize DirectoryInfo object to the passed directory. 
         DirectoryInfo DirFiles = new DirectoryInfo(Directory);

         //Create a DateTime object to be initialized below.
         DateTime TheTime;

         //Get a list of files for the current directory.
         FileInfo[] Files = DirFiles.GetFiles();
         
         //Create a new instance of FileIOPermission with read 
         //permission to the current directory.
         FileIOPermission FilePermission = new FileIOPermission(FileIOPermissionAccess.Read, Directory);

         try
         {
            //Check the stack by making a demand.
            FilePermission.Demand();

            //If the demand succeeded, assert permission and 
            //perform the operation.
            FilePermission.Assert();

            for(int x = 0 ; x<= Files.Length -1 ; x++)
            {
               TheTime = File.GetCreationTime(Files[x].FullName);
               Console.WriteLine("File: {0} Created: {1:G}", Files[x].Name,TheTime );
            }
            // Revert the Assert when the operation is complete.
            CodeAccessPermission.RevertAssert();
         }
         //Catch a security exception and display an error.
         catch(SecurityException)
         {
            Console.WriteLine("You do not have permission to read this directory.");
         }                            
      }
   }
}
Option Explicit
Option Strict
Imports System
Imports System.IO
Imports System.Security
Imports System.Security.Permissions
Namespace OptimizedSecurity
   Public Class FileUtil      
      Public Sub New()
      End Sub
      Public Sub GetFileCreationTime(directory As String)
         'Initialize DirectoryInfo object to the passed directory. 
         Dim dirFiles As New DirectoryInfo(directory)
         'Create a DateTime object to be initialized below.
         Dim theTime As DateTime
         'Get a list of files for the current directory.
         Dim files As FileInfo() = dirFiles.GetFiles()
         'Create a new instance of FileIOPermission with read 
         'permission to the current directory.
         Dim filePermission As New FileIOPermission(FileIOPermissionAccess.Read, Directory)
         Try
            'Check the stack by making a demand.
            filePermission.Demand()
            'If the demand succeeded, assert permission and 
            'perform the operation.
            filePermission.Assert()
            Dim x As Integer
            For x = 0 To Files.Length - 1
               theTime = file.GetCreationTime(files(x).FullName)
               Console.WriteLine("File: {0} Created: {1:G}", files(x).Name, theTime)
            Next x
            ' Revert the Assert when the operation is complete.
            CodeAccessPermission.RevertAssert()
         'Catch a security exception and display an error.
         Catch
            Console.WriteLine("You do not have permission to read this directory.")
         End Try
      End Sub
   End Class
End Namespace

Se a demanda no exemplo anterior tiver êxito, todos os arquivos e sua data de criação e time serão exibidos para o diretório passado.Se a demanda falhar, a exceção de segurança é interceptada e a seguinte mensagem é exibida no console:

You do not have permission to read this directory.

Suprimindo as demandas de permissão de código não gerenciado

Uma otimização especial está disponível para código que tenha permissão para telefonar código não gerenciado.Essa otimização permite que seu código gerenciado telefonar código não gerenciado sem incorrer a sobrecarga de uma pilha walk.Declarar a permissão de código não gerenciado pode reduzir a movimentação da pilha, mas a otimização descrita neste tópico pode eliminá-lo inteiramente.(See SecurityPermission Para obter mais informações sobre a permissão para telefonar código não gerenciado.)

Normalmente, uma telefonar no código não gerenciado gera uma demanda de permissão de código não gerenciado, o que resultados em um exame da pilha que determina se todos os chamadores tem permissão para chamar código não gerenciado.Aplicar o atributo personalizado SuppressUnmanagedCodeSecurityAttribute para o método que chama códigos não gerenciados suprime a demanda. Esse atributo substitui o exame da pilha completa em time de execução com uma verificação de que somente verifica as permissões do chamador imediato em time de vinculação.Na verdade, usar esse atributo cria uma porta aberta em código não gerenciado.Somente o código que tenha permissão de código não gerenciado pode usar esse atributo; caso contrário, ela não tem efeito.

Cuidado:

Use o SuppressUnmanagedCodeSecurityAttribute atributo apenas com muito cuidado.Uso incorreto desse atributo pode criar vulnerabilidades de segurança.The SuppressUnmanagedCodeSecurityAttribute atributo nunca deve ser usado para permitir que código menos confiável (código que não tenha permissão de código não gerenciado) telefonar código não gerenciado.

Esse atributo é pontos de melhor entrada aplicada somente a declarado em particular para código não gerenciado para que o código em outros módulos (assemblies) não é possível acesso e usufruir a supressão de segurança.Normalmente, o código gerenciado altamente confiável que usa esse atributo primeiro exige alguns permissão de chamadores antes de invocar o código não gerenciado em nome do chamador.

O exemplo a seguir mostra o SuppressUnmanagedCodeSecurityAttribute atributo aplicado a um ponto de entrada particular.

<SuppressUnmanagedCodeSecurityAttribute()> Private Declare Sub 
EntryPoint Lib "some.dll"(args As String)
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("some.dll")]
private static extern void EntryPoint(string args);

No caso raro em código não gerenciado que é completamente seguro para possíveis circunstâncias, um método com o SuppressUnmanagedCodeSecurityAttribute atributo pode ser exposto a outros códigos gerenciados diretamente, tornando-o público em vez de particular.Se você optar por expor um método que possui o SuppressUnmanagedCodeSecurityAttribute atributo, a funcionalidade do código não gerenciado deve ser não somente seguro mas também impenetrável por ataques por chamadores mal-intencionados.Por exemplo, o código deve operar corretamente mesmo quando não intencionais argumentos são gerados especificamente fazer com que o código não funcione corretamente.

Usando o declarativas substituições e demandas imperativa

Declarações e outras substituições são mais rápidas quando declarativamente, enquanto as demandas são mais rápidas quando imperativamente feita.Embora os ganhos de desempenho não podem ser drásticas, uso declarativo substitui e demandas imperativas podem ajudar você melhorar o desempenho do código.

Consulte também

Conceitos

Escrevendo seguro classe bibliotecas

Referência

File.GetCreationTime

SecurityPermission

SuppressUnmanagedCodeSecurityAttribute

Outros recursos

Segurança de Acesso de código