Россия, г. Москва |
Промежуточная среда .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, причем для этого не требуется что либо менять в коде клиента или сервера. Однако даже в простейшем случае реализация собственных поставщиков и труб выглядит достаточно громоздко.