Как программно отключить безопасность в WCF - PullRequest
8 голосов
/ 12 ноября 2009

Я работал с WCF последние два дня, и он отлично работал с сервером и клиентом на моей машине для разработки. Теперь, когда я пытаюсь провести некоторое распределенное тестирование с клиентом на другом компьютере в сети, у меня начались проблемы. Сейчас я получаю ошибку:

Сообщение с действием 'http://tempuri.org/IWindowUpdateContract/UpdateWindowFrames' не может быть обработано в получателе из-за несоответствия ContractFilter в EndpointDispatcher. Это может быть связано либо с несоответствием контракта (несоответствующие действия между отправителем и получателем), либо с несоответствием привязки / безопасности между отправителем и получателем. Убедитесь, что отправитель и получатель имеют одинаковый контракт и одинаковую привязку (включая требования безопасности, например, Сообщение, Транспорт, Нет).

Поскольку это уже огромный опыт обучения (я не делал никаких удаленных действий, RPC и др. Ранее), я хочу продолжить разработку инструмента обучения и вернуться к безопасности, когда я закончу (я не собираюсь ничего строить это будет фактически использоваться без надлежащей практики безопасности).

Примечания:

  • У меня нет настройки файла конфигурации для WCF - я все делаю программно.
  • Моя сеть не является частью домена, поэтому настройки безопасности по умолчанию у меня не работали (с помощью net.tcp).
  • Я использую .Net 3.5.

Мой сервер создан так:

    var svh = new ServiceHost(_serviceImplementation);

    var binding = new NetTcpBinding();

    binding.ReaderQuotas.MaxArrayLength = 2000000;
    binding.Security.Mode = SecurityMode.None;
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
    binding.Security.Transport.ProtectionLevel = ProtectionLevel.None;
    binding.Security.Message.ClientCredentialType = MessageCredentialType.None;

    svh.AddServiceEndpoint(_serviceInterface, binding, string.Format("net.tcp://{0}:{1}", _endPoint.Address, _endPoint.Port));

    _stopFlag = new AutoResetEvent(false);

    svh.Open();

    _stopFlag.WaitOne();

И мой клиент создан так:

    var binding = new NetTcpBinding();

    binding.ReaderQuotas.MaxArrayLength = 2000000;
    binding.Security.Mode = SecurityMode.None;
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
    binding.Security.Transport.ProtectionLevel = ProtectionLevel.None;
    binding.Security.Message.ClientCredentialType = MessageCredentialType.None;

    var scf = new ChannelFactory<IUserInputContract>(binding, "net.tcp://192.168.0.42:8001");
    _uiUpdateServer = scf.CreateChannel();

И мой контракт (который находится только в библиотеке классов, добавляемой как ссылка как на клиент, так и на сервер):

    [ServiceContract(ProtectionLevel = ProtectionLevel.None)]
    public interface IWindowUpdateContract {
        [OperationContract]
        void UpdateWindowFrames(WindowFrame frame);
        [OperationContract]
        void WindowHasClosed(IntPtr hwnd);
}

Мне кажется, что выполненные мной настройки привязки и контракта должны сделать их идентичными, и у меня не должно быть этой проблемы (и безопасность должна быть отключена). Я просто не знаю, куда идти.

1 Ответ

10 голосов
/ 12 ноября 2009

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

Примечание на стороне: как только вы сделаете:

binding.Security.Mode = SecurityMode.None;

Не думаю, что вам нужно указывать какие-либо дополнительные настройки для объекта "binding.Security" или ниже - эти дополнительные строки после этого не нужны.

Что привлекло мое внимание, так это ваш контракт на обслуживание:

[ServiceContract(ProtectionLevel = ProtectionLevel.None)]
public interface IWindowUpdateContract 
{
    [OperationContract]
    void UpdateWindowFrames(WindowFrame frame);
    [OperationContract]
    void WindowHasClosed(IntPtr hwnd);
}

Эти операции ничего не возвращают - это необычно. Поведение по умолчанию для службы WCF - Запрос / Ответ - вы отправляете запрос и получаете ответ.

Либо заставьте их вернуть что-то (состояние или что-то подобное; например, строку, целое число), либо вам нужно будет пометить их как «односторонние» вызовы, чтобы WCF знал, что ничего не ждет назад: *

[ServiceContract(ProtectionLevel = ProtectionLevel.None)]
public interface IWindowUpdateContract 
{
    [OperationContract(IsOneWay=true)]
    void UpdateWindowFrames(WindowFrame frame);
    [OperationContract(IsOneWay=true)]
    void WindowHasClosed(IntPtr hwnd);
}

Марк

...