.NET 4.0应用程序在网络共享上导致安全性异常

10

今天我在尝试远程调试一款针对.NET 4.0运行时构建的应用程序时遇到了一个奇怪的问题。

应用程序位于网络共享上,并由远程计算机执行。但是,每次在加载期间由System.Configuration.ConfigurationManager.GetSection()方法引发的权限要求导致SecurityException而导致应用程序崩溃。我还没有检查基类库中是否存在其他权限要求也会导致安全异常,但在所有情况下,这不应该在新CLR中发生。

该应用程序在完全信任下运行(在调试过程中检查并且通常对于CLR 4.0中的内部网络应用程序来说,这必须始终为真),因此我不知道在这种情况下如何通过权限要求引起异常。当针对3.5 SP1运行时进行构建时(默认情况下首次引入了网络共享应用程序的完全信任),每件事都按预期运行。

我在下面粘贴了示例代码。非常感谢您的任何帮助。

using System;
using System.Configuration;

namespace ConsoleApplication1
{
public sealed class AssetsSection : ConfigurationSection
{
    private static readonly ConfigurationProperty           s_propPath;
    private static readonly ConfigurationPropertyCollection s_properties;

    static AssetsSection()
    {
        s_propPath = new ConfigurationProperty("path", typeof(String));

        s_properties = new ConfigurationPropertyCollection()
        {
            s_propPath
        };
    }

    public static AssetsSection Get()
    {
        return (AssetsSection) ConfigurationManager.GetSection("test/assets");
    }

    protected override ConfigurationPropertyCollection Properties
    {
        get
        {
            return s_properties;
        }
    }

    public String Path
    {
        get
        {
            return (String) base[s_propPath];
        }
        set
        {
            base[s_propPath] = value;
        }
    }
}

class Program
{
    static void Main(String[] args)
    {
        Console.WriteLine(AssetsSection.Get().Path);

        Console.ReadLine();
    }
}
}

还有 App.config 文件;

<?xml version="1.0"?>
<configuration>
<configSections>
    <sectionGroup name="test">
        <section name="assets" type="ConsoleApplication1.AssetsSection, ConsoleApplication1"/>
    </sectionGroup>
</configSections>

<startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
</startup>

<test>
    <assets path="..\Assets"/>
</test>
</configuration>

为什么您要为.NET 4.0构建,但强制其运行旧版本的CLR? - Hans Passant
抱歉,我从我的测试代码中复制了错误的配置文件。我已经编辑了问题。然而,问题当然仍然存在。 - David
4个回答

17
尝试首先加载配置文件,然后打开你所在的部分:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AssetsSection configSection = (AssetsSection)config.GetSection("test/assets");

我遇到了与.NET 4相同的问题,这对我有效。


非常感谢Timo。这对我也有用。但我认为这是.NET 4.0中的一个bug。 - David
1
请注意,虽然这种方法可以解决异常问题,但存在性能问题:反序列化的 XML 没有被缓存,每次调用 OpenExeConfiguration() 都会发生。使用 GetSection() 的“正确”(有缺陷的)方式会缓存部分 XML,并在后续调用中重复使用它。这可能会影响应用程序的性能,具体取决于您的应用程序对性能的敏感程度以及您调用 OpenExeConfiguration 的频率。 - galaktor

4

这是由于在从网络共享运行应用程序时,.NET 4.0中已知的一个错误。

下面的代码会因为SecurityException而失败。请注意,仅当您为该部分定义了自定义类型(例如此示例中的AssetsSection)时,才会失败:

ConfigurationManager.GetSection("test/assets");

一种解决方法是Timo提出使用不同的API。另一种解决方法是应用微软提供的补丁。

与此Bug相关的Hotfix已在KB2580188中列出。


1
如果您添加自己的类来映射该部分,可以这样做:

[XmlRoot("Interface")]
public class MySectionClass
{
    [XmlAttribute()]
    public string MyAttr1
    {
        get;
        set;
    }

    public string MyAttr2
    {
        get;
        set;
    }
}

你可以使用这段代码:
ConfigurationSection configSection = 
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).
GetSection("MySection");

XmlSerializer xs = new XmlSerializer(typeof(MySectionClass));

XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(configSection.SectionInformation.GetRawXml());

XmlNodeReader xnr = new XmlNodeReader(xdoc.DocumentElement);

MySectionClass section = (MySectionClass)xs.Deserialize(xnr);

-1
我在这里推测,但我怀疑是您的配置文件不受信任。
在您的情况下,您的配置文件引用了一个没有强名称可用作证据的类型ConsoleApplication1.AssetsSection
您能否提供更多细节和确切的错误消息。

我有同样的问题,我的应用程序配置看起来像这样,但我仍然有问题:<section name="AuthenticationSection" type="Cnbv.Sait.Configuration.AuthenticationConfigurationSection, Cnbv.Sait.Configuration, Version=4.0.12.0, Culture=neutral, PublicKeyToken=51d456dd8a5ff4be" requirePermission="false" />。 - Juan Zamudio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接