Как передать больше данных, чем имя пользователя / пароль, методу службы в службе WCF 4.0 RESTful, используя обычную аутентификацию
Требования:
WCF 4.0 IIS host Базовая аутентификация с пользовательским источником RESTful
Существует множество примеров и способов реализации базовой аутентификации, от использования UserNamePasswordValidator, через ServiceAuthorizationManager и IDispatchMessageInspector и т. Д.
Проблема, с которой я сталкиваюсь, заключается в том, что проверка на самом деле будет получать гораздо больше информации из бэкэнда аутентификации, чем ответ да / нет. И я хочу как-то передать эту информацию вызываемым сервисным методам (то есть это будет полноценный объект User со многими свойствами для управления поведением сервиса). Я хочу избежать повторного вызова хранилища пользователей для получения данных на основе имени пользователя, к которому я могу получить доступ из контекста безопасности.
Пока что самое близкое, что я обнаружил, - это решение, в котором используется RequestInterceptor начального набора WCF REST, в котором я могу внедрить подкласс ServiceSecurityContext для переноса моих данных и привести ServiceSecurityContext.Current обратно в метод service.
Проблема с вышеупомянутым состоит в том, что он написан для WCF 3.5, и что я хотел бы избежать использования Starter Kit.
Вопрос: любая идея, что было бы наиболее подходящим местом для цепочки в цепочке, чтобы я мог передать данные из логики валидации в сервис. Или, другими словами, где я мог бы заменить контекст безопасности на мой собственный, чтобы нести нагрузку? Или любой другой механизм несущей?
Что мне нужно, так это поведение:
Клиент (может быть браузером) пытается использовать службу: GET https://myservcer/service/data Сервер отвечает "Требуется базовая аутентификация" Клиент предоставляет заголовок базовой аутентификации и снова отправляет запрос Сервер на основе пользователя /pass в заголовке, вытаскивает объект User из базы данных. Если пользователь не найден, запросите аутентификацию снова. Если пользователь найден, объект User каким-то образом передается сервисному методу. Все это должно происходить без повторного обращения к базе данных.
Пока что я понимаю, что UserNamePasswordValidator не будет делать - нет способа передать объект User, если я получу его там.
Я могу создать пользовательский IAuthorizationPolicy или SecurityToken (который) и поместить объект User. Но... где это должно произойти. Могу ли я пойти с UserNameSecurityTokenAuthenticator для этого? Будет ли возвращаться правильный код ошибки HTTP для запроса учетных данных? Как / где я изменяю web.config, чтобы использовать мои собственные вещи? Пока я вижу, как установить использование только пользовательского UserNamePasswordAuthenticator.
РЕДАКТИРОВАТЬ: пожалуйста, проверьте мой собственный ответ для моего подхода. Тем не менее вопрос был хорош, и ответы, которые я получил, были ценными.
3 ответа
Мы внедрили наш собственный модуль HTTP аутентификации. Модуль подключается к событию "Проверка подлинности по запросу" приложения HttpApplication и запускает проверку подлинности на основе серверной части. Сервер может свободно возвращать все, что хочет (и в нашем случае он возвращает больше, чем да / нет. Возвращаемый объект реализует интерфейс System.Security.Principal.IIdentity. После успешной аутентификации мы присоединяем идентификатор (объект, возвращаемый auth) субъекту, который переносится в HttpContext.User.
Вниз по конвейеру вы можете получить доступ к пользователю текущего контекста в любой момент и получить всю информацию о вашей личности.
Единственный существенный недостаток этого подхода заключается в том, что он требует совместимости с ASP.net, но если вы уже используете подобные службы Rest, это не должно быть проблемой.
Я закончил тем, что вообще не использовал WCF. Нэнси было намного проще создавать и тестировать RESTFull API, и с последними изменениями (это будет в версии 0.8) то, о чем я спрашивал, стало очень легко.
Вы можете создать реализацию IAuthorizationPolicy и заменить основной идентификатор на тот, который вы получаете во время аутентификации. Посмотрите на эти ссылки, которые показывают, как избежать попадания в базу данных дважды: