Защита службы WCF с помощью basicHttpBinding, которая поддерживает потоковое

Мой вопрос касается наилучшего (так называемого "наименее болезненного" ) способа обеспечения доступа к службе WCF, которая доступна только для внутренних пользователей нашей компании. Цель состоит в том, чтобы обеспечить доступ к службе только через одно приложение форм Windows, установленное каждым из наших пользователей. Когда вызывается служба, я хочу, чтобы служба могла проверить, что она вызывается из разрешенного приложения.

Служба, которая должна быть защищена, использует basicHttpBinding, которая поддерживает потоковое вещание, поэтому я считаю, что я ограничен защитой на уровне транспорта.

Ниже приведены упрощенные версии разделов <bindings> и <services> из моего конфигурационного файла службы.

<bindings>
  <basicHttpBinding>
    <binding name="Service1Binding" transferMode="Streamed"/>    
  </basicHttpBinding>
</bindings>

<services>
    <service name="WCFServiceSecurity.Service1" 
        behaviorConfiguration="WCFServiceSecurity.Service1Behavior">
        <endpoint address=""
            binding="basicHttpBinding"
            contract="WCFServiceSecurity.IService1"
            bindingConfiguration="Service1Binding"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
</services>

Может ли кто-нибудь предложить какие-то сведения о том, какие действия мне потребуется предпринять для обеспечения безопасности этой службы?

Примечание. Я новичок в WCF и вообще не знаком с безопасностью, поэтому дайте мне знать, если я не предоставил достаточно подробностей.


UPDATE:

Как предложенный marc_s, я хотел бы защитить службу WCF с помощью своего рода механизма имени пользователя и пароля. Это дает немного больше указания на ответ, но я все еще несколько расплывчато, как на самом деле это делать.

Поскольку моя служба требует, чтобы потоковая передача была включена, я должен использовать basicHttpBinding и уровень безопасности на транспортном уровне (правильно?); кроме того, метод, содержащийся в моей службе, может принимать только объект Stream.

Учитывая эти ограничения, наряду с моим предпочтением использовать проверку имени пользователя и пароля...

  • Как мне изменить конфигурационный файл службы, чтобы указать учетные данные для имени пользователя и пароля?
  • Как моя служба проверит предоставленные учетные данные?
  • Как мое клиентское приложение будет передавать учетные данные службе при совершении вызова?
  • Будет ли это требовать использования SSL, и если да, будут ли все клиентские компьютеры также иметь сертификат?

UPDATE:

После объяснения проблемы, с которой я столкнулся, чтобы обеспечить эту услугу моему боссу, мне дали добро, чтобы попробовать маршрут проверки подлинности Windows. К сожалению, мне не повезло в реализации этого типа аутентификации с моей службой Streamed (argh). После внесения соответствующих изменений (как указано здесь - единственное исключение - это мой transferMode="Streamed") и доступ к моей службе, мне представили следующая ошибка:

Потоковая передача HTTP-запросов не может использоваться в сочетании с HTTP-аутентификацией. Либо отключите поток запросов, либо укажите анонимную HTTP-аутентификацию.

Затем я наткнулся на следующую цитату здесь, которая предлагает некоторые пояснения:

Вы не можете использовать auth. с потоковой передачей. Если вам нужно использовать потоки HTTP-запросов, вам придется работать без безопасности.

Способ обеспечения безопасности:

Клиент WCF делает HTTP-запрос для сервера.

Сервер отвечает тем, что говорит: "Вы не авторизованы, пришлите мне базовый/дайджест/etc."

Клиент получает этот ответ и отправляет свое сообщение с прикрепленными учетными данными.

Теперь сервер получает сообщение, проверяет учетные данные и продолжает. Поток запросов не предназначен для работы с этим шаблоном безопасности. Если бы это было так, это было бы очень медленно, так как Клиент отправил бы весь поток, получив сообщение от Сервера, что он не авторизовался, тогда ему придется повторно отправить весь поток с учетными данными.

Итак, теперь я ищу мнения, , как бы вы обеспечили поддержку службы WCF с поддержкой потоковой передачи? Как уже упоминалось ранее, предпочтительным будет какой-то механизм имени пользователя и пароля. Не стесняйтесь думать вне коробки на этом...

Любая помощь значительно оценена!

Ответ 1

Хорошо, я нашел много проблем, связанных с безопасностью/потоковой передачей при работе над этой проблемой. Hack (er... um... обходной путь). Наконец, я решил создать новый DataContract, который наследует MemoryStream и украсит его свойством BaseStream (для хранения данных, которые я хочу передать) вместе с соответствующими свойствами, используемыми для простая аутентификация.

Вот результат DataContract:

[DataContract]
[KnownType( typeof( MemoryStream ) )] 
public class StreamWithCredentials : MemoryStream
{
    [DataMember]
    public Stream BaseStream { get; set; }

    [DataMember]
    public string Username { get; set; }

    [DataMember]
    public string Password { get; set; }
}

Вышеуказанный DataContract становится входным параметром моего метода обслуживания. Первым действием, которое выполняет моя служба, является аутентификация предоставленных учетных данных с известными действительными значениями и продолжение по мере необходимости.

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

Это, как говорится, было лучшим решением вышеупомянутой проблемы, которую я мог бы придумать, надеюсь, что это поможет кому бы то ни было, затронутому этой проблемой.

Спасибо всем, кто ответил.

Ответ 2

Здесь вы можете сделать несколько вещей:

  • добавьте сертификат на каждую машину, которая разрешает использовать вашу службу, и проверьте этот сертификат. Это позволяет вам исключить "несанкционированные" машины - вы не можете ограничить его конкретным приложением.
  • как и выше, но включите сертификат, встроенный в ваше приложение winforms, и отправьте его оттуда (не храните его в хранилище сертификатов)
  • требуется имя пользователя/пароль, о которых только ваше конкретное приложение знает и может передать вашу услугу; например кто-то еще не сможет представить соответствующие учетные данные

РЕДАКТИРОВАТЬ 2: ОК, поэтому подход с именем пользователя/пароля, похоже, выходит из-под контроля... что если у вас есть базовая транспортная безопасность (SSL) для базовой защиты, а затем используйте MessageContract для определения заголовка и тело вашего сообщения SOAP, укажите конкретное значение в заголовке, а затем просто проверьте наличие этого элемента в заголовке в своей службе?

Что-то вроде этого:

[DataContract]
class YourRequestData
{
 ...
}

[MessageContract]
public class YourRequest
{
  [MessageBodyMember]
  public YourRequestData bodyData { get; set; }

  [MessageHeader]
  public string AppThumbprint { get; set; }
}

И затем на вашем сервере в вашем коде просто проверьте наличие и достоверность этого кода AppThumbprint:

public Stream RequestStream(YourRequest request)
{
  if(AppThumbprintIsValid(request.AppThumbprint))
  {
     .... begin your streaming
  }
}

Это может оказаться намного проще, чем сценарий безопасности имени пользователя и пароля.

Марк

Ответ 3

Если вы хотите использовать basicHttpBinding (для взаимодействия), вы можете передавать свои учетные данные только на уровне сообщений. Вы должны установить свою конфигурацию безопасности TransportWithMessageCredential.

Для этого вам необходимо создать SSL-канал, поэтому вам нужен сертификат на стороне сервера, и для клиента не обязательно иметь его.

Ответ 4

Пожалуйста, поправьте меня, если я ошибаюсь, но:

если вы используете проверку подлинности форм для своей службы WCf (на asp.net), просто добавьте метод входа в свою службу, в ней вы создадите необходимый файл cookie (formsAuthentication.Authenticate()). который автоматически отправляется с ответом, клиент может затем вызывать API потока, не требуя дополнительных параметров (требование для него быть STREAM), и вы можете проверить идентификатор в потоковой api, прежде чем запускать возвращаемый поток.

Что касается обеспечения доступа ко всему WCF, то возникает ощущение, что внедрение сертификата в приложение .net - это один из способов. они должны будут использовать ваше приложение, чтобы добраться до него.

вы можете указать asp.net/wcf не предоставлять wsdl или, точнее, не автоматически генерировать wsdl. Без доступа wsdl им становится намного сложнее генерировать прокси-сервер....

Ответ 5

Можно использовать проверку подлинности Windows с помощью потоковой передачи и SSL, но вы должны использовать TransportWithMessageCredential:

<basicHttpBinding>
    <binding name="FileService.FileServiceBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
        <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
        <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Windows" />
        </security>
    </binding>
</basicHttpBinding>

Вам нужно установить код proxy.ClientCredentials.UserName.UserName и proxy.ClientCredentials.UserName.Password.

Ответ 6

Если это будет приложение, которое живет в интрасети, может быть проще всего создать новую группу в Active Directory и предоставить членам этой группы возможность использовать эту услугу.

Вы можете добавить аутентификацию (используя учетные данные Windows) с чем-то вроде этого:

<basicHttpBinding> 
 <security mode="TransportCredentialOnly"> 
  <transport clientCredentialType="Windows" /> 
 </security> 
</basicHttpBinding> 

Можно ли авторизовать, украсив интерфейс вашими методами обслуживания:

<PrincipalPermission(SecurityAction.Demand, Role:="MyAppsUsers")> _ 
Public Function MyMethod() As String Implements IService.MyMethod 

Вот хорошая ссылка на Security в WCF. В нем много вариантов "Как в конце" (для вас может быть полезен один под названием "Как использовать - Использовать basicHttpBinding с Windows Authentication and TransportCreditals" ).
Wcf Secruity

[Отказ от ответственности: я также новичок в WCF и не делал этого точного дела, прежде чем так извиняюсь, если это немного отключено!]