Предположим, что я рассматриваю возможность создания службы WCF, основной целью которой является предоставление широких услуг, которые могут использоваться тремя разрозненными приложениями: публичным веб-сайтом, внутренним приложением Windows Forms и беспроводным мобильным устройством. Цель службы двоякая: (1) консолидировать код, связанный с бизнес-процессами в центральном местоположении, и (2) заблокировать доступ к устаревшей базе данных, наконец, и раз и навсегда скрывать ее за одним пакетом услуг.
В настоящее время каждое из трех приложений имеет свои собственные уровни персистентности и домена с немного разными представлениями одной и той же базы данных. Вместо того, чтобы все три приложения разговаривали с базой данных, они разговаривали с сервисом WCF, предоставляя новые функции от некоторых клиентов (мобильная сборщик не может в настоящее время запускать процессы для отправки электронной почты, очевидно) и централизации систем уведомлений (вместо запланированное задание опроса базы данных каждые пять минут для новых заказов, просто пинг системы служебного пейджинга, когда один из этих клиентов вызывает метод службы AcceptNewOrder()
). В целом, это звучит довольно разумно до сих пор.
В плане общего дизайна, однако, я в тупике, когда дело доходит до безопасности. Приложение Windows Forms в настоящее время просто использует ОС Windows; сотрудники хранятся в Active Directory, а при запуске приложений они могут войти в систему как текущий пользователь Windows (в этом случае пароль не требуется), или они могут предоставить свое доменное имя и пароль. У мобильного клиента нет понятия пользователя; его соединение с базой данных является жестко обозначенной строкой. И веб-сайт содержит тысячи пользователей, хранящихся в старой базе данных. Итак, как мне реализовать модель идентификации и настроить конечные точки WCF, чтобы справиться с этим?
Что касается приложения Windows Forms, это не является большой проблемой: прокси-сервер WCF может быть инициирован один раз и может зависать в памяти, поэтому мне нужны только учетные данные клиента один раз (и может запрашивать их снова, если прокси-сервер когда-либо неисправности). Мобильный клиент может просто быть специальным и использовать сертификат X509 для аутентификации против службы WCF. Но что мне делать с веб-сайтом?
В случае веб-сайта разрешен анонимный доступ к некоторым службам. А для служб, требующих аутентификации в гипотетической роли "Заказчик", я, очевидно, не хочу, чтобы они проверяли их по каждому запросу по двум причинам:
- Мне нужно их имя пользователя и пароль каждый раз. Хранение этой информации практически в любом месте - сеанс, зашифрованный файл cookie, луна - кажется плохой идеей.
- Мне пришлось бы ударить по таблице пользователей в базе данных для каждого запроса. Уч.
Единственное решение, которое я могу придумать, - это рассматривать веб-сайт как доверенную подсистему. Служба WCF ожидает получения определенного сертификата X509 с веб-сайта. Веб-сайт, используя внутреннюю аутентификацию форм (которая вызывает метод AuthenticateCustomer()
для службы, которая возвращает логический результат), может добавить дополнительную заявку в список учетных данных, например, "[email protected] зарегистрирован как клиент." Затем каким-то образом пользовательский объект IIdentity и IPrincipal могут быть сконструированы на службе с этим требованием, а служба WCF уверена, что веб-сайт правильно аутентифицировал клиента (он будет знать, что требование не было подделано, по крайней мере, потому что он будет знать сертификат веб-сайта раньше времени).
Используя все это, код службы WCF мог бы говорить такие вещи, как [PrincipalPermission.Demand(Role=MyRoles.Customer)]
или [PrincipalPermission.Demand(Role=MyRoles.Manager)]
, а Thread.CurrentPrincipal
- то, что представляло пользователя (адрес электронной почты для клиента или отличительное имя для сотрудника, оба из которых полезны для ведения журнала и аудита).
Другими словами, для каждой службы будут существовать две разные конечные точки: одна, которая принимает общеизвестные клиентские сертификаты X509 (для мобильных устройств и веб-сайта), и для тех, кто принимает пользователей Windows (для сотрудников).
Жаль, что это так долго. Поэтому возникает вопрос: имеет ли смысл это? Имеет ли смысл предлагаемое решение? И я делаю это слишком сложно?