Веб-сайт ASP.NET + приложение Windows Forms + сервис WCF: удостоверения клиента

18
задан Nicholas Piasecki 5 December 2008 в 22:39
поделиться

2 ответа

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

Мой первый подход должен был настроить основанную на сертификате аутентификацию между сервисом WCF, и общедоступный веб-сайт (веб-сайт является потребителем/клиентом сервиса). Несколько тестовых сертификатов генерировали с makecert, шлепнитесь их в Personal, Trusted People, и Trusted Root Certification Authorities (потому что я не мог быть побеспокоен для генерации реальных против служб сертификации нашего домена), некоторые модификации файла конфигурации, и большой, мы все установлены.

, Чтобы препятствовать тому, чтобы веб-сайт имел для поддержания имени пользователя и информации о пароле для пользователей, идея состоит в том, что, после того как пользователь зарегистрирован в веб-сайт через Аутентификацию Форм, веб-сайт может передать просто имя пользователя (доступный через HttpContext.Current.User.Identity.Name) как дополнительное UserNameSecurityToken в дополнение к X509CertificateSecurityToken, который на самом деле используется для обеспечения сообщения. Если бы дополнительный маркер безопасности имени пользователя найден, то сервис WCF сказал бы "Эй, эта доверяемая подсистема говорит, что этот пользователь правильно аутентифицируется, таким образом позвольте мне настроить MyCustomPrincipal для того пользователя и установить его на текущем потоке так, чтобы код практической эксплуатации мог осмотреть это". Если бы это не было, то анонимная версия MyCustomPrincipal была бы установлена.

Так прочь я пошел в течение пяти часов, пытаясь реализовать это, и с помощью [1 124] различный блоги , я смог сделать это. (Я провел большую часть своего времени, отлаживая проблему, где я имел каждую конфигурацию и корректный класс поддержки, и затем установил мои пользовательские полномочия после , я запустил хост, не прежде, таким образом, ни одно из моего усилия на самом деле не вступало в силу. В некоторые дни я ненавижу компьютеры.) Я имел TrustedSubsystemAuthorizationPolicy, который сделал проверку сертификата X509, установив анонимное MyCustomPrincipal, TrustedSubsystemImpersonationAuthorizationPolicy, который принял маркер имени пользователя с пустым паролем и установил клиентскую роль MyCustomPrincipal, если она видела, что анонимный доверяемый принципал подсистемы был уже установлен, и UserNameAuthorizationPolicy, который сделал регулярное имя пользователя и основанную на пароле проверку для других конечных точек, где сертификаты X509 не используются. Это работало, и это было замечательно.

, Но.

stab-myself-in-the-eyeballs момент наступил, когда я играл со сгенерированным клиентским кодом прокси, который веб-сайт будет использовать, чтобы говорить с этим сервисом. При определении UserName на ClientCredentials свойство сгенерированного ClientBase<T> объект был достаточно легок. Но основная проблема состоит в том, что учетные данные характерны для ChannelFactory, не конкретный вызов метода.

Вы видите, новый () луг клиентский прокси WCF более дорог , чем [1 127], Вы могли бы думать . Я записал быстрое-и-грязное приложение в проведение испытаний сам: оба новые () луг новый прокси и вызов метода десять раз заняли приблизительно 6 секунд тогда как новый () луг прокси однажды и вызов только метода стоимость 10 раз о 3/5ths одной секунды. Это - просто угнетающее различие в производительности.

, Таким образом, я могу просто реализовать пул или кэш для клиентского прокси, правильно? Ну, нет, это легко не работало вокруг: информация об удостоверениях клиента на уровне фабрики канала, потому что это могло бы использоваться для обеспечения транспорта, не только сообщения, и некоторая привязка сохраняет фактический транспорт открытым между служебными вызовами. Так как удостоверения клиента уникальны для объекта прокси, это означает, что у меня должен был бы быть уникальный кэшируемый экземпляр для каждого пользователя в настоящее время на веб-сайте. Это - потенциально много объектов прокси, находящихся в памяти, и симпатичный # $ # близко к проблеме, которой я старался избегать во-первых! И так как я должен затронуть Endpoint свойство так или иначе для установки привязки для дополнительного маркера имени пользователя поддержки, я не могу использовать в своих интересах автоматическая фабрика канала, кэширующаяся , который Microsoft добавила "бесплатно" в.NET 3.5.

Назад к исходной точке: мой второй подход и тот, что я думаю, что закончу тем, что использовал на данный момент, должны придерживаться защиты сертификатом X509 между клиентским веб-сайтом и сервисом WCF. Я просто отправлю пользовательскому "Имени пользователя" заголовок SOAP в своих сообщениях, и сервис WCF может осмотреть тот заголовок SOAP, определить, прибыл ли он из доверяемой подсистемы, такой как веб-сайт, и если так, установите MyCustomPrincipal подобным образом как прежде.

Codeproject и случайные люди на Google являются замечательными вещами иметь, потому что они помогли мне разбудить это и работающий быстро, даже после столкновение со странной ошибкой WCF когда дело доходит до пользовательских поведений конечной точки в конфигурации . Путем реализации инспекторов сообщения на стороне клиента и сервисной стороне - один для добавления заголовка UserName, и один, чтобы считать его и установить корректный принципал - этот код находится в одном месте, где я могу просто забыть об этом. Так как я не должен затрагивать Endpoint свойство, я получаю встроенную фабрику канала, кэширующуюся бесплатно. И начиная с эти ClientCredentials то же для любого пользователя, получающего доступ к веб-сайту (действительно, они всегда - сертификат X509 - только значение заголовка UserName в рамках самого сообщения изменяется), добавляя клиентское кэширование на прокси-сервере, или пул прокси намного более тривиален.

, Таким образом, это - то, что я закончил тем, что делал. Код практической эксплуатации в сервисе WCF может сделать вещи как [1 143]


    // Scenario 1: X509Cert + custom UserName header yields for a Web site customer ...
    Console.WriteLine("{0}", Thread.CurrentPrincipal.Identity.Name); // prints out, say, "joe@example.com"
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Customer)); // prints out "True"

    // Scenario 2: My custom UserNameSecurityToken authentication yields for an employee ...
    Console.WriteLine("{0}", Thread.CurrentPrincipal.Identity.Name); // prints out, say, CN=Nick,DC=example, DC=com
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Employee)); // prints out "True"

    // Scenario 3: Web site doesn't pass in a UserName header ...
    Console.WriteLine("{0}", Thread.CurrentPrincipal.Identity.Name); // prints out nothing
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Guest)); // prints out "True"
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Customer)); // prints out "False"

, не имеет значения, как эти люди аутентифицировались, или что некоторые живут в SQL-сервере или что некоторые живут в Active Directory: PrincipalPermission.Demand и регистрирующийся для аудита целей теперь снимок.

я надеюсь, что это помогает некоторой плохой душе в будущем.

15
ответ дан 30 November 2019 в 09:19
поделиться

Поскольку anonymouse открытый доступ использует basichttpbinding и также имеет следующее в web.config файле

0
ответ дан 30 November 2019 в 09:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: