Защита службы WCF с помощью BasicHttpBinding, который поддерживает потоковую передачу.
-
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 и еще не занимался этим конкретным случаем, поэтому прошу прощения, если это немного не так!]