混合安全和放大不安全的渠道

时间:2010-03-30 11:17:52

标签: c# .net security remoting

一旦安全通道已经注册,我就无法使用不安全的通道。以下代码仅在客户端,以前注册了不安全的通道时才有效。

是否可以在不对注册订单进行任何约束的情况下混合安全和不安全的渠道?

using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

public class SampleObject : MarshalByRefObject
{
    public DateTime GetTest() { return DateTime.Now; }
}
public class SampleObject2 : MarshalByRefObject
{
    public DateTime GetTest2() { return DateTime.Now; }
}
static class ProgramClient
{
    private static TcpClientChannel RegisterChannel(bool secure, string name, int priority)
    {
        IDictionary properties = new Hashtable();
        properties.Add("secure", secure);
        properties.Add("name", name);
        properties.Add("priority", priority);
        var clientChannel = new TcpClientChannel(properties, null);
        ChannelServices.RegisterChannel(clientChannel, false);
        return clientChannel;
    }
    private static void Secure()
    {
        RegisterChannel(true, "clientSecure", 2);
        var testSecure = (SampleObject2)Activator.GetObject(typeof(SampleObject2), "tcp://127.0.0.1:8081/Secured.rem");
        Console.WriteLine("secure: " + testSecure.GetTest2().ToLongTimeString());
    }
    private static void Unsecure()
    {
        RegisterChannel(false, "clientUnsecure", 1);
        var test = (SampleObject)Activator.GetObject(typeof(SampleObject), "tcp://127.0.0.1:8080/Unsecured.rem");
        Console.WriteLine("unsecure: " + test.GetTest().ToLongTimeString());
    }
    internal static void MainClient()
    {
        Console.Write("Press Enter to start.");
        Console.ReadLine();
        // Works only in this order
        Unsecure();
        Secure();
        Console.WriteLine("Press ENTER to end");
        Console.ReadLine();
    }
}
static class ProgramServer
{
    private static TcpServerChannel RegisterChannel(int port, bool secure, string name)
    {
        IDictionary properties = new Hashtable();
        properties.Add("port", port);
        properties.Add("secure", secure);
        properties.Add("name", name);
        //properties.Add("impersonate", false);
        var serverChannel = new TcpServerChannel(properties, null);
        ChannelServices.RegisterChannel(serverChannel, secure);
        return serverChannel;
    }
    private static void StartUnsecure()
    {
        RegisterChannel(8080, false, "unsecure");
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(SampleObject), "Unsecured.rem", WellKnownObjectMode.Singleton);
    }
    private static void StartSecure()
    {
        RegisterChannel(8081, true, "secure");
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(SampleObject2), "Secured.rem", WellKnownObjectMode.Singleton);
    }
    internal static void MainServer()
    {
        StartUnsecure();
        StartSecure();
        Console.WriteLine("Unsecure: 8080\n Secure: 8081");
        Console.WriteLine("Press the enter key to exit...");
        Console.ReadLine();
    }
}
class Program
{
    static void Main(string[] args)
    {
        if (args.Length == 1 && args[0] == "server")
            ProgramServer.MainServer();
        else
            ProgramClient.MainClient();
    }
}

编辑:.NET 4和VS 2010没有变化。

1 个答案:

答案 0 :(得分:1)

这是一个有趣的复古问题,我花了大约一个星期试图解决这个问题,并且不得不实施一个解决方案。但这是我发现的:答案很可能是:不,你不能。

说明:.NET远程处理不允许您选择在创建对象时使用哪个客户端通道。在服务器端,显然会使用监听有问题端口的通道,但在客户端,它只会使用任何可用的,甚至可以创建一个新的 - 尽管我总是注册我自己的。

所以看来(我在文档中找不到它)如果有可用的安全客户端通道,则会使用该通道。因此,在问题的示例中,远程对象是针对安全通道创建的,但它期望不安全 - 因此它会失败。如果首先创建一个不安全的连接 - 它的工作原理是因为在创建远程对象时没有安全的客户端通道,因此使用了不安全的客户端通道。

替代方法:

  1. 为安全通道创建单独的AppDomain。
  2. 在该AppDomain中,创建一个连接到安全的客户端对象。
  3. 对所有不安全的渠道使用默认的AppDomain。