ASP.NET security exception with OpenWebConfigurati

2019-07-17 08:34发布

问题:

After moving my web site from my local development environment to a shared host I get:

Security Exception 

Description: The application attempted to perform an operation not allowed by 
the security policy.  To grant this application the required permission please
contact your system administrator or change the application's trust level in 
the configuration file.

The problem occurs in my web application everywhere the following is called:

WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)

Since my web application is only trying to open it's own web.config file, I don't know why this is flagged as a security exception. Maybe someone can explain... But more importantly I need a solution, the couple solutions I found via Google are painful.

One solution (from numerous posts) said to configure the trust level to Full, but I'm told that is not possible on my shared host.

Another solution (from http://www.4guysfromrolla.com/articles/100307-1.aspx) says to not use OpenWebConfiguration(), but I need to use it to encrypt configuration sections (e.g. connectionStrings) using DPAPI (for more info see http://www.4guysfromrolla.com/articles/021506-1.aspx).

Please advise on why IIS barfs on my web application trying to open it's own web.config, and a work-around to be able to encrypt parts of the web.config using DPAPI.

回答1:

I have had experience of this issue in the past. The OpenWebConfiguration() method also reads the machine.config file. Under partial trust and without the correct permissions you can't use this method.

If you were to step into the .NET Framework assemblies with your debugger in Visual Studio 2008/2010 you can see exactly what is happening.

The following is a call stack captured when stepping into WebConfigurationManager.OpenWebConfiguration():

mscorlib.dll!System.IO.FileStream.Init(string path = "C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\Config\\machine.config", System.IO.FileMode mode = Open, System.IO.FileAccess access = Read, int rights = 0, bool useRights = false, System.IO.FileShare share = Read, int bufferSize = 4096, System.IO.FileOptions options = None, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs = null, string msgPath = "machine.config", bool bFromProxy = false) Line 326 C#

mscorlib.dll!System.IO.FileStream.FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) Line 259 C#

System.Configuration.dll!System.Configuration.Internal.InternalConfigHost.StaticOpenStreamForRead(string streamName) + 0x56 bytes 

System.Configuration.dll!System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.OpenStreamForRead(string streamName, bool assertPermissions) + 0x7d bytes 

System.Configuration.dll!System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.OpenStreamForRead(string streamName) + 0xb bytes 

System.Configuration.dll!System.Configuration.Internal.DelegatingConfigHost.OpenStreamForRead(string streamName) + 0xe bytes 

System.Configuration.dll!System.Configuration.UpdateConfigHost.OpenStreamForRead(string streamName) + 0x2f bytes 

System.Configuration.dll!System.Configuration.BaseConfigurationRecord.InitConfigFromFile() + 0x126 bytes 

System.Configuration.dll!System.Configuration.BaseConfigurationRecord.Init(System.Configuration.Internal.IInternalConfigRoot configRoot, System.Configuration.BaseConfigurationRecord parent, string configPath, string locationSubPath) + 0xaa5 bytes 

System.Configuration.dll!System.Configuration.MgmtConfigurationRecord.Init(System.Configuration.Internal.IInternalConfigRoot configRoot, System.Configuration.Internal.IInternalConfigRecord parent, string configPath, string locationSubPath) + 0x39 bytes 

System.Configuration.dll!System.Configuration.MgmtConfigurationRecord.Create(System.Configuration.Internal.IInternalConfigRoot configRoot, System.Configuration.Internal.IInternalConfigRecord parent, string configPath, string locationSubPath) + 0x2a bytes 

System.Configuration.dll!System.Configuration.Internal.InternalConfigRoot.GetConfigRecord(string configPath) + 0x12d bytes 

System.Configuration.dll!System.Configuration.Configuration.Configuration(string locationSubPath, System.Type typeConfigHost, object[] hostInitConfigurationParams) + 0xfd bytes 

System.Configuration.dll!System.Configuration.Internal.InternalConfigConfigurationFactory.System.Configuration.Internal.IInternalConfigConfigurationFactory.Create(System.Type typeConfigHost, object[] hostInitConfigurationParams) + 0x1e bytes 

System.Web.dll!System.Web.Configuration.WebConfigurationHost.OpenConfiguration(System.Web.Configuration.WebLevel webLevel, System.Configuration.ConfigurationFileMap fileMap, System.Web.VirtualPath path, string site, string locationSubPath, string server, string userName, string password, System.IntPtr tokenHandle) Line 862 C#

System.Web.dll!System.Web.Configuration.WebConfigurationManager.OpenWebConfigurationImpl(System.Web.Configuration.WebLevel webLevel, System.Configuration.ConfigurationFileMap fileMap, string path, string site, string locationSubPath, string server, string userName, string password, System.IntPtr userToken) Line 77 + 0x1c bytes C#

System.Web.dll!System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(string path) Line 140 + 0x25 bytes C#

Unfortunately your only alternative is to use WebConfigurationManager.GetSection() which isn't as feature rich.

With regard to encrypting your connection strings. Sadly this feature demands Full Trust, there's no other way around it.