Защита службы WCF с помощью BasicHttpBinding, который поддерживает потоковую передачу.

StackOverflow https://stackoverflow.com/questions/845423

  •  21-08-2019
  •  | 
  •  

Вопрос

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

Служба, которую необходимо защитить, использует 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 и совсем не знаком с безопасностью, поэтому дайте мне знать, если я не предоставил достаточно подробностей.


ОБНОВЛЯТЬ:

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

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

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

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

ОБНОВЛЯТЬ:

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

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

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

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

Безопасность работает следующим образом:

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

Сервер отвечает чем-то вроде: «Вы не авторизованы, пришлите мне базовые/дайджест/и т. д. учетные данные».

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

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

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

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

Это было полезно?

Решение

Что ж, во время работы над этой проблемой я обнаружил множество проблем, связанных с безопасностью/потоковой передачей.Хак (э-э-э... обходной путь), который я в конце концов выбрал, заключался в том, чтобы создать новый 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 (что я даже не уверен, что это возможно - как уже говорилось здесь) для этого внутреннего процесса.

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

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

Другие советы

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

  • добавьте сертификат на каждый компьютер, которому разрешено использовать ваш сервис, и проверьте наличие этого сертификата.Это позволяет вам только исключить «неавторизованные» машины — вы не можете ограничить это конкретным приложением.
  • то же, что и выше, но включите сертификат, встроенный в ваше приложение 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
  }
}

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

Марк

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

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

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

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

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

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

Можно использовать аутентификацию 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.

Если это будет приложение, которое будет находиться в интрасети, возможно, проще всего просто создать новую группу в 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 

Вот хорошая ссылка на безопасность в WCF.В конце содержится множество инструкций (вам может пригодиться статья под названием «Как использовать базовую привязку HttpBinding с проверкой подлинности Windows и TransportCreditals»).
ВКФ Безопасность

[Отказ от ответственности:Я также новичок в WCF и еще не занимался этим конкретным случаем, поэтому прошу прощения, если это немного не так!]

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top