Mensagem de erro "Acesso negado" ocorre quando você representar uma conta no ASP.NET e chamar componentes COM STA

IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.

Clique aqui para ver a versão em Inglês deste artigo: 325791
Sintomas
Se você representa uma conta específica in ASP.NET Web Service (.asmx) ou em seu formulário da Web (.aspx) e, em seguida, você chamar a um componente COM (Apartment/Single-threaded Component Object Model), a identidade do processo (por padrão, a conta ASPNET) é usada em vez da conta representada. Portanto, os erros lógicos podem ocorrer quando tentar acessar recursos do componente COM, ou você pode receber a seguinte mensagem de erro:
Acesso negado
Causa
O thread que executa sua solicitação ASP.NET é um dos threads de E/s ou um dos workerThreads no processo de operador do ASP.NET (aspnet_wp.exe). Esses segmentos são todos os threads MTA (Multi-Threaded Apartment). Se você representar programaticamente uma conta em seu código .aspx ou .asmx, ou se você representar usando <identity impersonate="true"> em Web.config ou Machine.config, em seguida, o token de representação é mantido nesse thread MTA. Se você fizer uma chamada em um single-threaded ou COM um segmento de apartamento, em seguida, componente, esse componente é acessado por um thread totalmente diferente, que é o único thread em seu STA (Single-Threaded Apartment). Porque este STA thread não tem um token de representação das suas próprias e o símbolo de representação do thread MTA não é passado para o thread STA, o segmento STA, em seguida, executa sob a identidade de processo.
Resolução
Para contornar este problema para formulários da Web ou para Web Services, você pode fazer o seguinte:

Para formulários da Web (.aspx)

Usar AspCompat = "true" para executar a página em um thread STA e evitar a opção de thread quando você chamar o componente.

Consulte Q308095 na seção "Referências" deste artigo para obter mais informações.

Para serviços da Web (.asmx)

AspCompat não está disponível para serviços da Web (.asmx), portanto, você deve usar uma abordagem diferente. Se a conta representada for estática, que significa que você especificar uma senha e um userName na marca <identity> de Web.config ou Machine.config, ou se você representar sempre programaticamente a mesma conta, poderá colocar o componente STA em um aplicativo de servidor do COM + e, em seguida, definir a identidade do aplicativo para o usuário representado.

Observação Quando você chamar uma thread apartment ou single-threaded COM o componente de um Web Service, ele já é um requisito para colocar o componente em algum tipo de aplicativo COM +.

Consulte Q303375 na seção "Referências" deste artigo para obter mais informações.

Se a conta representada for dinâmica (<identity impersonate="true"> + integrado do IIS ou autenticação básica), definir a identidade em um aplicativo COM + para servidor não será suficiente. Nesse caso, se você controlar o código para o componente STA, em seguida, você pode chamar ofunção CoImpersonateClient no início de cada método no componente que requer a identidade representada. Se você não controlar o código para o STA. componente, ou se o código para o componente é escrito por um terceiro, você pode introduzir um componente STA de wrapper que chama CoImpersonateClient primeiro e, em seguida, chama no componente de terceiros. Há duas abordagens que você pode usar:
  • Se você deve usar ligação inicial de seus clientes, você pode criar um componente de wrapper separado para cada componente de terceiros. Cada componente de wrapper precisa separar os métodos de invólucro para cada método no seu componente de terceiros.
  • Se você pode usar ligação tardia dos clientes, você pode criar apenas um componente de invólucro genérica. Este componente wrapper pode criar qualquer componente de terceiros usando o ProgID, e seria necessário apenas um método genérico Invoke para chamar os componentes de terceiros.
Consulte a função CallByName na seção "Referências" deste artigo para obter mais informações.

O exemplo a seguir mostra como você pode:
  • Criar um novo thread STA
  • Passar dados para o novo thread
  • Fazer com que o novo thread ser executado sob a mesma identidade que o serviço da Web está representando
  • Aguarde o novo thread concluir a chamada a STA componente
  • Extraia os resultados do novo thread e retornar os resultados para o cliente
Observação O objetivo deste exemplo é somente mostrar como usar seu próprios STA segmento para representar e acessar o componente COM diretamente. Em um ambiente de produção, é melhor gerenciar um pool de segmentos do STA em vez de criação e destruição de um único segmento em cada solicitação.

Se você usar o exemplo a segue, o thread STA é destruído imediatamente após chamar o componente COM e, em seguida, você não pode fazer referência quaisquer outros objetos COM que foram criados neste STA. Portanto, se seu objeto COM retorna uma referência a um segundo objeto COM criado no STA mesma, você receberá a seguinte InvalidComObjectException :
Objeto COM que foi separado do seu RCW subjacente não pode ser usado
.

Para fazer esse trabalho, você deve manter o thread STA funcionamento e bomba, em seguida, as mensagens para invocar o segundo objeto COM, que está além do escopo deste exemplo.

Criar um arquivo de texto com permissões limitados

  1. Crie um arquivo de texto chamado C:\permissions.txt. Insira algum texto para o arquivo.
  2. Clique com o botão direito do mouse Permissions.txt no Microsoft Windows Explorer e, em seguida, clique em Propriedades .
  3. Na guia Segurança, remova todos os usuários e, em seguida, forneça controle total para o usuário que está conectado no momento.

Criar um componente COM STA para acessar o arquivo de texto

  1. Crie um novo projeto Microsoft Visual Basic 6 ActiveX DLL chamado FSOWrapper.
  2. Adicionar um novo módulo de classe chamado CMyFileSystemObject e cole-o no código a seguir:
       Option ExplicitDim m_fso As FileSystemObjectPrivate Sub Class_Initialize()    Set m_fso = New FileSystemObjectEnd SubPublic Function OpenTextFileUsingDefaults(ByVal FileName As String) As CMyTextStream    Set OpenTextFileUsingDefaults = OpenTextFile(FileName)End FunctionPublic Function OpenTextFile( _    ByVal FileName As String, _    Optional ByVal IOMode As IOMode = ForReading, _    Optional ByVal Create As Boolean = False, _    Optional ByVal Format As Tristate = TristateFalse) As CMyTextStream        Dim oStream As TextStream    Set oStream = m_fso.OpenTextFile(FileName, IOMode, Create, Format)        Set OpenTextFile = New CMyTextStream    OpenTextFile.Init oStreamEnd Function					
  3. Adicionar um novo módulo de classe chamado CMyTextStream e cole-o no código a seguir:
    Option ExplicitDim m_oStream As TextStreamFriend Sub Init(oStream As TextStream)    Set m_oStream = oStreamEnd SubPublic Function ReadAll() As String    ReadAll = m_oStream.ReadAllEnd Function					
  4. Compile FSOWrapper.dll.

Criar um WebService para chamar o componente COM STA

  1. Crie um novo projeto translation from VPE for Csharp ASP.NET WebService no Microsoft Visual Studio .NET.
  2. No campo local, digite http://localhost/STAWebService
  3. O IIS snap-in do MMC, visite o diretório virtual STAWebService e em seguida, clique em Propriedades . Verifique se a autenticação integrada do Windows é o método de autenticação apenas que está selecionada.
  4. Adicione o seguinte no nó <system.web> do arquivo Web.config: <identity impersonate="true"/>
  5. Cole o código seguinte a Service1.asmx.cs arquivo:
using System;using System.Web.Services; using FSOWrapper;using System.Threading;using System.Security.Principal;using System.Runtime.InteropServices;using System.Text; namespace STAWebService{       [WebService()]       public class Service1 : WebService       {                           /// Create an STA thread under the current impersonated identity              /// so that it can access the STA DLL directly without losing the impersonation.              [WebMethod]              public string TestOpenFileFromSTA(string sFile)              {                     StringBuilder returnString = new StringBuilder();                     try                     {                           // Start the output...                           StartOutput(returnString);                            // Create/init our MySTAThread object.                           MySTAThread myThread = new MySTAThread(sFile);                            // Start up this new STA thread.                           myThread.Start();                            // Wait for the new thread to finish.                           bool bWaitRet = myThread.Event.WaitOne(1000,false);                            // Finish the output...                           FinishOutput(returnString, bWaitRet, myThread);                     }                     catch (Exception e)                     {                           returnString.Append("<Exception_in_original_thread message = \"" + e.Message + "\"/>");                     }                      return returnString.ToString();              }               private void StartOutput(StringBuilder returnString)              {                     returnString.Append("<Results_from_original_thread>");                     returnString.Append("<OriginalIdentity value = \"" + WindowsIdentity.GetCurrent().Name + "\"/>");              }              private void FinishOutput(StringBuilder returnString, bool bWaitRet, MySTAThread myThread)              {                     returnString.Append("<FinalIdentity value = \"" + WindowsIdentity.GetCurrent().Name + "\"/>");                     returnString.Append("<Done_within_timeout value = \"" + bWaitRet + "\"/>");                     returnString.Append("</Results_from_original_thread>");                                                                                                       returnString.Append("<Results_from_myThread>");                     returnString.Append("<Success value = \"" + myThread.Success + "\"/>");                     returnString.Append("<ImpersonatedIdentity value = \"" + myThread.ImpersonatedIdentity + "\"/>");                     returnString.Append("<FileContents value = \"" + myThread.FileContents + "\"/>");                     returnString.Append("<Exception value = \"" + myThread.Exception + "\"/>");                     returnString.Append("</Results_from_myThread>");              }       }       public class MySTAThread       {              [DllImport("advapi32")]              public static extern bool RevertToSelf();               // You can use public members (or properties) for output...              public bool Success;              public string FileContents;              public string Exception;                        public string ImpersonatedIdentity;               // Public event so caller can wait.              public AutoResetEvent Event;               // Privates...              Thread theThread;              WindowsIdentity impersonatedIdentity;              string fileName;               public MySTAThread(string fileName)              {                     // Init values;                     Success = false;                     Exception = "There was no error!";                     this.fileName = fileName;                      // Create Thread and Event.                      Event = new AutoResetEvent(false);                                                        theThread = new Thread(new ThreadStart(MySTAThreadStart));                      // Intialize to an STA so that there will be no thread switch to the STA COM object.                     theThread.ApartmentState = ApartmentState.STA;              }               public void Start()              {                     // Hang on to the current (impersonated) Identity.                     impersonatedIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();                      // This thread is currently impersonating so any thread you start                      // will not have permission to impersonate. You must drop the                      // current impersonation token so that your new thread can impersonate.                     RevertToSelf();                      // Start up the new thread.                     theThread.Start();                      // Return to the original (impersonated) identity.                     impersonatedIdentity.Impersonate();              }               void MySTAThreadStart()              {                     try                     {                                 // Impersonate using the Token property.                           WindowsImpersonationContext ctx = impersonatedIdentity.Impersonate();                            // Store current name of the user for verification.                           ImpersonatedIdentity = (WindowsIdentity.GetCurrent().Name);                                                // Access some STA COM object that requires impersonation.                           CMyFileSystemObject oMyFSO = new CMyFileSystemObjectClass();                           CMyTextStream oMyTxtStream = oMyFSO.OpenTextFileUsingDefaults(fileName);                           FileContents = oMyTxtStream.ReadAll();                           Success = true;                     }                     catch(Exception e)                     {                           Exception = e.Message ;                           Success = false;                     }                     finally                     {                           // Drop the impersonation token now that you are finished with it.                           RevertToSelf();                            // Set the Event property so that the creator can stop waiting on this thread.                           Event.Set();                     }              }       }}				

Execute o WebService a partir do Internet Explorer

  1. Clique em Debug | Start Without Debugging menu (CTRL+F5) para iniciar WebService no Internet Explorer.
  2. Clique no link OpenFileFromSTA .
  3. Digite C:\permissions.txt para o campo sFile e, em seguida, clique em Invoke .

    Na nova página, você pode ver código semelhante ao seguinte:
  <?xml version="1.0" encoding="utf-8" ?><string xmlns="http://tempuri.org/">       <Results_from_original_thread>              <OriginalIdentity value="MYDOMAIN\myuser" />              <FinalIdentity value="MYDOMAIN\myuser" />              <Done_within_timeout value="True" />       </Results_from_original_thread>       <Results_from_myThread>              <Success value="True" />              <ImpersonatedIdentity value="MYDOMAIN\myuser" />              <FileContents value="this is some stuff in the file." />              <Exception value="There was no error!" />       </Results_from_myThread></string>				
Situação
Esse comportamento é por design.
Referências
Para obter mais informações, clique nos números abaixo para ler os artigos na Base de dados de Conhecimento da Microsoft:
308095Criando componentes STA no construtor modo ASPCOMPAT ASP.NET negativamente afeta o desempenho
303375XML Web services e objetos de compartimento
306158Como implementar a representação em um aplicativo ASP.NET
306590Visão geral sobre a segurança do ASP.NET
Para obter informações adicionais, visite o site do MSDN:

Aviso: este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 325791 - Última Revisão: 03/22/2007 11:28:33 - Revisão: 3.6

Microsoft Web Services Enhancements para Microsoft .NET 1.1, Microsoft Web Services (included with the .NET Framework) 1.0, Microsoft COM+ 2.0 Standard Edition

  • kbmt kbclient kbdevsecurity kbprb kbsecurity KB325791 KbMtpt
Comentários