Опубликован: 11.05.2007 | Доступ: свободный | Студентов: 1700 / 236 | Оценка: 4.36 / 4.25 | Длительность: 16:06:00
Лекция 10:

Промежуточная среда .NET Remoting

Труба шифрования клиента должна зашифровать этот поток перед отправкой на сервер и расшифровать при получении ответа сервера.

class EncryptedClientChannelSink: IClientChannelSink
    {
        public IDictionary Properties
        {   
            get { return null; }
        }
        
        private IClientChannelSink nextSink;
        
        public IClientChannelSink NextChannelSink
        { 
            get { return nextSink;  }
        }
               
        private SymmetricEncryptor encryptor;
               
        public EncryptedClientChannelSink(SymmetricEncryptor channelEncryptor,
            IClientChannelSink next)
        {
            encryptor = channelEncryptor; 
            nextSink = next;
        }            
        
        public void ProcessMessage(IMessage message, 
            ITransportHeaders requestHeaders, Stream requestStream,
            out ITransportHeaders responseHeaders, out Stream responseStream)
        {                        
            MemoryStream encryptedStream = new MemoryStream();            
            Stream serverStream = null;
            
            // Зашифровать запрос клиента
            encryptor.Encrypt(requestStream, encryptedStream);
            encryptedStream.Position = 0;
            
            nextSink.ProcessMessage(message, requestHeaders, encryptedStream, 
                out responseHeaders, out serverStream);
            
            serverStream = Utils.ReadAllStream(serverStream);
            
            // Расшифровать ответ сервера
            responseStream = new MemoryStream();
            encryptor.Decrypt(serverStream, responseStream);
            responseStream.Position = 0;
        }  
        
        public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
        { 
            return null; 
        }               
        public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, 
            IMessage message, ITransportHeaders headers, Stream stream) 
        {
            throw new NotSupportedException();
        }        
        
        public void AsyncProcessResponse(
            IClientResponseChannelSinkStack sinkStack, object state, 
            ITransportHeaders headers, Stream stream)
        {
            throw new NotSupportedException();
        }        
    } // EncryptedClientChannelSink
Листинг 8.3.

Вспомогательный класс Utils служит для считывания всего содержимого потока, не поддерживающего свойство Length.

public static class Utils
  {
     public static MemoryStream ReadAllStream(Stream input)
     {
         byte[] buffer = new byte [1024];
         MemoryStream output = new MemoryStream();
         while (true)
         {
             int read = input.Read(buffer, 0, buffer.Length);
             output.Write(buffer, 0, read);                    
             if (read < buffer.Length) break;                
         }    
         output.Position = 0;            
         return output;
     }
 }
}
// SevaRemotingEncrypted.cs

Для компиляции указанных файлов можно использовать следующий make-файл.

makefile : Client.exe SevaRemotingEncrypted.dll
common = Seva*.cs 

Client.exe : Client.cs RemoteService.dll
    csc /r:RemoteService.dll Client.cs

RemoteService.dll : RemoteService.cs 
    csc /t:library RemoteService.cs 

SevaRemotingEncrypted.dll: $(common)
    csc /out:SevaRemotingEncrypted.dll /t:library $(common)

Как видно из данного файла, при компиляции клиент не ссылается на сборку с модифицированными поставщиками труб. Регистрация данных поставщиков труб происходит с помощью файлов конфигурации.

<configuration>
   <system.runtime.remoting>
      <application>
         <client>
            <wellknown 
               type="RemoteService.RemoteServiceTest, RemoteService"
               url="tcp://localhost:10020/endpoint"
            />
         </client>
         <channels>
            <channel ref ="tcp">
               <clientProviders>
                <formatter  ref="binary"/>
                <provider  type="Seva.Remoting.Encryption.
                    EncryptedClientChannelSinkProvider, SevaRemotingEncrypted"
                    key="secret.key"
                  />
               </clientProviders>
            </channel>
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

Таким образом, архитектура .NET Remoting позволяет встраивать собственные трубы в канал Remoting, причем для этого не требуется что либо менять в коде клиента или сервера. Однако даже в простейшем случае реализация собственных поставщиков и труб выглядит достаточно громоздко.