2010-03-30 24 views
19

Non riesco a utilizzare un canale non sicuro una volta che un canale protetto è già stato registrato. Il codice seguente funziona solo se sul lato client, il canale non protetto è registrato in precedenza.Combinazione di canali sicuri e non protetti

È possibile combinare canali sicuri e non protetti senza alcun vincolo nell'ordine di registrazione?

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(); 
    } 
} 

Edit: Nessun cambiamento con .NET 4 e VS 2010.

+3

Si dice che "non funziona"; potresti chiarire cosa sta facendo? –

+0

@ M.Babcock Il tuo commento fa riferimento a una domanda molto vecchia, per utilizzare chi non è attivo da alcuni mesi. Just fyi –

+0

Sapevo che era una domanda abbastanza vecchia, ma ho capito che è ancora rilevante dal momento che i moderatori non l'hanno ancora disattivato. Sentiti libero di cancellare la mia risposta se ritieni che non sia necessario. –

risposta

1

questo è interessante domanda d'epoca, ho trascorso circa una settimana cercando di risolvere questo problema, e ha dovuto implementare un work-around. Ma ecco quello che ho scoperto: la risposta è più probabile: NO, NON PUOI.

Spiegazione: .NET remoting non consente di scegliere quale canale client utilizzare quando si crea un oggetto. Sul lato server, userebbe il canale che ascolta la porta in questione, ovviamente, ma dal lato del client ne userebbe solo uno disponibile o ne creerebbe uno nuovo - anche se registro sempre il mio.

Quindi sembra (non sono riuscito a trovarlo da nessuna parte nella documentazione) che se c'è un canale client sicuro disponibile, quello viene usato. Quindi, nell'esempio nella domanda, l'oggetto remoto viene creato rispetto al canale sicuro, ma si aspetta uno non sicuro, quindi fallisce. In caso di creazione di una connessione non sicura per prima, funziona perché al momento della creazione dell'oggetto remoto non esiste un canale client sicuro, quindi viene utilizzato il canale del client non sicuro.

SOLUZIONE:

  1. Creare un AppDomain separato per, per esempio, un canale protetto.
  2. In quell'AppDomain, creare un oggetto client che si connetterebbe alla sicurezza.
  3. Utilizza l'AppDomain predefinito per tutti i canali non sicuri.
Problemi correlati