Подтвердить что ты не робот

Смешивание безопасных и незащищенных каналов

Я не могу использовать незащищенный канал, как только защищенный канал уже зарегистрирован. Код ниже работает только в том случае, если на стороне клиента незащищенный канал зарегистрирован ранее.

Можно ли смешивать безопасные и незащищенные каналы без каких-либо ограничений на порядок регистрации?

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.

4b9b3361

Ответ 1

Это интересный старинный вопрос, который я потратил около недели, пытаясь решить эту проблему, и должен был выполнить обход. Но вот что я обнаружил: ответ скорее всего: НЕТ, ВЫ НЕ МОЖЕТЕ.

Объяснение:.NET remoting не позволяет вам выбирать, какой клиентский канал использовать при создании объекта. Очевидно, что на стороне сервера он будет использовать канал, который прослушивает данный порт, но на стороне клиента он будет использовать любой доступный или даже создать новый, хотя я всегда регистрирую свой собственный.

Итак, кажется (я не мог найти его где-либо в документации), что если есть доступный доступный клиентский канал, он будет использоваться. Итак, в примере в вопросе удаленный объект создается против защищенного канала, но он ожидает небезопасного - поэтому он терпит неудачу. В случае создания небезопасного соединения сначала - это работает, потому что во время создания удаленного объекта отсутствует безопасный клиентский канал, поэтому используется небезопасный клиентский канал.

WORKAROUND:

  • Создайте отдельный AppDomain для, например, защищенного канала.
  • В этом AppDomain создайте клиентский объект, который будет подключаться к безопасному.
  • Используйте свой AppDomain по умолчанию для всех небезопасных каналов.