Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article vous aide à résoudre le System.Security.SecurityException
problème levée lorsque vous utilisez la System.Net.HttpWebRequest
classe à partir d’une application Windows Forms basée sur Microsoft .NET Framework 3.5 SP1.
Version du produit d’origine : Microsoft .NET Framework 3.5 Service Pack 1
Numéro de base de connaissances d’origine : 2512713
Symptômes
Vous utilisez la System.Net.HttpWebRequest
classe à partir d’une application Windows Forms basée sur Microsoft .NET Framework 3.5 Service Pack 1 de manière synchrone. Plus précisément, ce code s’exécute sur le thread principal ou d’interface utilisateur. Votre application Windows Forms lève une exception intermittente de type System.Security.SecurityException
qui a un message similaire à ce qui suit :
La demande d’autorisation de type « System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 » a échoué.
L’exception affiche une pile d’appels défaillante semblable à ce qui suit :
0:000> !clrstack
ESP EIP
<<ESP>> <<EIP>> System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)
<<ESP>> <<EIP>> System.Threading.WaitHandle.WaitOne(Int64, Boolean)
<<ESP>> <<EIP>> System.Threading.WaitHandle.WaitOne(Int32, Boolean)
<<ESP>> <<EIP>> System.Net.NetworkAddressChangePolled.CheckAndReset()
<<ESP>> <<EIP>> System.Net.NclUtilities.get_LocalAddresses()
<<ESP>> <<EIP>> System.Net.WebProxyScriptHelper.myIpAddress()
.........
.........
<<ESP>> <<EIP>> System.Net.WebProxyScriptHelper+MyMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.CallOneOfTheMembers(System.Reflection.MemberInfo[], System.Object[], Boolean, System.Object, System.Reflection.Binder, System.Globalization.CultureInfo, System.String[], Microsoft.JScript.Vsa.VsaEngine, Boolean ByRef)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.Call(System.Reflection.Binder, System.Object[], System.Reflection.ParameterModifier[], System.Globalization.CultureInfo, System.String[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.Call(System.Object[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine).........
.........
<<ESP>> <<EIP>> Microsoft.JScript.JSMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.FunctionObject.Call(System.Object[], System.Object, Microsoft.JScript.ScriptObject, Microsoft.JScript.Closure, System.Reflection.Binder, System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.Closure.Call(System.Object[], System.Object, System.Reflection.Binder, System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.CallValue(System.Object, System.Object[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine, System.Object, System.Reflection.Binder, System.Globalization.CultureInfo, System.String[])
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.CallValue(System.Object, System.Object, System.Object[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine)
.........
.........
<<ESP>> <<EIP>> System.Reflection.MethodBase.Invoke(System.Object, System.Object[])
<<ESP>> <<EIP>> System.Net.VsaWebProxyScript.CallMethod(System.Object, System.String, System.Object[])
<<ESP>> <<EIP>> System.Net.VsaWebProxyScript.Run(System.String, System.String)
.........
.........
<<ESP>> <<EIP>> System.Net.IWebProxyScript.Run(System.String, System.String)
<<ESP>> <<EIP>> System.Net.AutoWebProxyScriptEngine.GetProxies(System.Uri, Boolean, System.Net.AutoWebProxyState ByRef, Int32 ByRef)
<<ESP>> <<EIP>> System.Net.WebProxy.GetProxiesAuto(System.Uri, System.Net.AutoWebProxyState ByRef, Int32 ByRef)
<<ESP>> <<EIP>> System.Net.ProxyScriptChain.GetNextProxy(System.Uri ByRef)
<<ESP>> <<EIP>> System.Net.ProxyChain+ProxyEnumerator.MoveNext()
<<ESP>> <<EIP>> System.Net.ServicePointManager.FindServicePoint(System.Uri, System.Net.IWebProxy, System.Net.ProxyChain ByRef, System.Net.HttpAbortDelegate ByRef, Int32 ByRef)
<<ESP>> <<EIP>> System.Net.HttpWebRequest.FindServicePoint(Boolean)
<<ESP>> <<EIP>> System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
<<ESP>> <<EIP>> System.Net.HttpWebRequest.GetRequestStream().........
.........
<<ESP>> <<EIP>> YourApplicationFunction.....
.........
.........
La cause
Lorsque la System.Net.HttpWebRequest
classe est exécutée à partir du thread principal, qui est également le thread d’interface utilisateur, il peut être nécessaire d’exécuter le protocole WPAD (Détection automatique du proxy web) pour détecter si un proxy est requis pour atteindre l’URL de destination. Pendant ce processus, System.Net
télécharge et compile le script PAC (Proxy Auto-Configuration) en mémoire et tente d’exécuter la FindProxyForURL
fonction conformément à la spécification PAC.
Dans ce cas, System.Net
crée un domaine d’application interne à l’intérieur de l’application qui s’exécute avec des autorisations minimales et surtout, il n’accorde pas l’autorisation d’interface utilisateur à ce nouveau domaine d’application. L’évaluation d’un proxy et l’exécution de la FindProxyForURL
fonction JavaScript se produit dans le contexte de ce nouveau domaine d’application et pendant ce processus System.Net
peut avoir besoin d’exécuter plusieurs fonctions d’assistance en fonction de la spécification PAC telle que isInNet
, dnsResolve
myIpAddress
pour calculer le proxy.
Par exemple, lors de l’exécution de la myIpAddress
fonction System.Net
, essayez d’évaluer l’adresse IP actuelle de l’ordinateur actuel et, à un moment donné, il peut avoir besoin d’utiliser l’appel System.Threading.WaitHandle.WaitOne()
de fonction. Lorsque cette System.Threading.WaitHandle.WaitOne()
fonction est appelée à partir du thread principal ou de l’interface utilisateur, cet appel continue de traiter les messages de fenêtre pendant son attente.
Si le message de fenêtre est traité pendant l’appel, le Common Language Runtime (CLR) du .NET Framework effectue une vérification complète de la WaitOne()
pile et demande l’autorisation de l’interface utilisateur. S’il trouve une incompatibilité dans les autorisations, une System.Security.SecurityException
exception est levée.
Résolution
Ce comportement est voulu.
Pour contourner ce problème, vous pouvez basculer vers l’utilisation asynchrone de la System.Net.HttpWebRequest
classe ou vous pouvez toujours utiliser l’approche synchrone, mais l’exécuter à partir d’un thread d’arrière-plan ou d’un thread autre que l’interface utilisateur. De cette façon, le processus de fenêtre aura un règne libre du thread d’interface utilisateur sans avoir à interrompre les appels d’attente dans un autre domaine d’application.
Une autre approche que vous pouvez utiliser consiste à conserver le même code qu’auparavant, mais au lieu d’exécuter System.Net
la détection automatique du proxy sur le thread principal, vous pouvez créer un thread et essayer d’exécuter la System.Net.WebProxy.GetProxy
fonction sur ce thread d’arrière-plan et laisser le thread d’arrière-plan effectuer la détection automatique du proxy. Une fois que le thread d’arrière-plan récupère l’adresse d’un serveur proxy, vous pouvez définir la Proxy
propriété de l’objet HttpWebRequest
et le définir sur un proxy fixe. Cela empêche la détection automatique du proxy sur le thread principal et ne lève pas l’exception.
Si votre environnement a un proxy fixe configuré, vous pouvez désactiver complètement la détection automatique du proxy en ajoutant les paramètres de configuration suivants dans votre fichier de configuration d’application :
<system.net>
<defaultProxy>
<proxy autoDetect="False" usesystemdefault="False" proxyaddress="http://yourProxy:yourProxyPort"/>
</defaultProxy>
</system.net>
Remarque
Bien que l’exécution de requêtes HTTP synchrones à l’aide de la System.Net.HttpWebRequest
classe fonctionne correctement dans la plupart des scénarios, nous vous déconseillons d’exécuter des opérations réseau synchrones telles que l’envoi de requêtes HTTP à partir du thread principal ou de l’interface utilisateur en raison de retards possibles rencontrés pendant les opérations réseau (telles que l’adresse IP ou la résolution DNS, la détection du proxy, etc.). Il est préférable d’exécuter ces requêtes synchrones à partir d’un thread d’arrière-plan ou d’exécuter les requêtes de manière asynchrone.