2009-07-05 2 views
10

Фоноваяудостовер ASP.NET веб-приложение с WCF службы

У меня есть веб-приложение ASP.NET, который взаимодействует с WCF сервисов. Веб-приложение и службы WCF находятся под моим контролем. В веб-приложении ASP.NET используется пользовательская реализация модели поставщика членства ASP.NET (с паролями, хранящимися в хешированной форме) для аутентификации пользователей, которые входят в веб-приложение. Как веб-приложение ASP.NET, так и службы WCF имеют доступ к одной и той же базе данных членства.

Поскольку пользователи будут предоставлять свой пароль только один раз, и я не хочу хранить их пароли в любом месте или раздражать их, неоднократно прося их пополнять свой пароль, мне нужен соответствующий механизм для аутентификации пользователей с помощью Услуги WCF.

Основываясь на других вопросах и ответах, которые я видел, я рассматриваю подход типа «входа в систему», в котором пользовательский сеанс будет создан в базе данных пользовательского членства, когда пользователь первоначально войдет в веб-приложение, с сеанс входа в систему, идентифицированный GUID, и автоматически истекает после периода бездействия. GUID сеанса входа будет «запоминаться» веб-приложением для каждого зарегистрированного пользователя (либо сохраненного в Билет проверки подлинности форм, либо в сеансе).

Служба WCF также будет предоставлять свою собственную операцию входа в систему, принимая имя пользователя и пароль и возвращая GUID сеанса входа, как описано выше.

Служба WCF затем примет GUID сеанса входа для всех других операций и проверит, что GUID представляет действительный сеанс входа в систему, который еще не истек, прежде чем разрешить операцию продолжить.

Я проделал довольно много фонового чтения, и есть много материала о прямом использовании типа учетных данных клиента UserName, но для этого потребуется, чтобы веб-приложение запоминало пароль пользователя, который не мне кажется отличной идеей.

Я провел некоторое исследование и нашел материал на MSDN, но это, похоже, требует много усилий для реализации того, что (по крайней мере для меня) похоже на довольно распространенный сценарий использования.

How to: Create a Custom Token

Вопрос

Является ли общий подход "сеанс", описанный выше разумного?
Если да, то каков наилучший способ его достижения?
Если нет, можете ли вы предложить альтернативу?

+0

Доступна ли ваша служба WCF только из внутренней сети? Если это так, я не вижу необходимости повторной проверки подлинности запросов. –

+0

Извините за упущение - услуга WCF будет доступна в Интернете. –

ответ

1

Спасибо всем за ваш вклад. Я остановился на подходе (по крайней мере пока). Это довольно просто и хорошо работает для моих целей.

Использование ClientEredentialType «UserName» и явный метод входа в систему, который возвращает токен безопасности (сведения о генерации маркера опущены для краткости), клиент службы может решить, передавать ли подлинный пароль в качестве свойства пароля на учетных данных клиента или токен безопасности (полученный из метода входа). Если клиент является веб-приложением, токен безопасности может быть сохранен в билете проверки подлинности форм или сеансе или где угодно.

Использование «Пользовательского» userNamePasswordValidationMode и пользовательской реализации UserNamePasswordValidator, проверка достоверности проверяет пароль, чтобы определить, является ли он действительным маркером безопасности или паролем - если это пароль, то учетные данные клиента аутентифицируются в хранилище пользователей (SQL База данных сервера), и если это токен безопасности, тогда он проверяется на то, чтобы он был действителен, не истек и принадлежит имени пользователя.

1

Есть два возможных решения я могу думать:

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

Во-вторых, вы храните имя пользователя и хэш пароля (или фактического пароля) где-то. Либо в состоянии сеанса, либо в cookie пользователя (файл cookie, хранящийся в памяти, передается пользователю через https). Затем передайте имя пользователя и пароль службе WCF с каждым запросом.

+1

Служба WCF будет доступна в Интернете. Если я храню хэш пароля, тогда мне нужно включить аутентификацию с помощью службы WCF с использованием хеша пароля - насколько я вижу это эффективно, это делает его просто паролем (хотя это было бы сложно/невозможно догадываться), но все же что-то, что было бы «постоянно» полезным, если было бы скомпрометировано (по крайней мере, пока пользователь не изменил свой пароль). Использование подхода к токенам сеанса входа, который я изначально описал, будет означать, что токен сеанса входа был действителен только на короткий период и был бы гораздо менее рискован, если бы был взломан. –

1

См. Мой ответ на вопрос Storing password in forms authentication cookie - ASP.NET and WCF calls для решения, которое не требует хранения паролей.

+0

Я прочитал ответ, который вы указали, прежде чем публиковать этот вопрос. Это звучит как интересный подход, но я немного туман на механике. Не могли бы вы пояснить или привести пример? –

+0

@Secret Squirrel, я расширил ответ на другой странице. –

2

Это очень разумный подход.

Для этого вы настраиваете свою конечную точку обслуживания и настраиваете ее с помощью своего пользовательского поставщика членства (вы можете сделать то же самое с поставщиком членства в SQL, для него не требуется специальный).

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

Теперь, когда вы совершаете вызов Службы через прокси-сервер WCF, эти учетные данные передаются через защищенный канал в службу и используют их для аутентификации.

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

protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e) 
{ 
    bool Authenticated = false; 
    try 
    { 
     MyServiceClient proxy = new MyServiceClient("MyServiceEndpoint"); 
     proxy.ClientCredentials.UserName.UserName = LoginControl.UserName; 
     proxy.ClientCredentials.UserName.Password = LoginControl.Password; 

     //It doesn't really matter what is called or what it does because 
     //Membership Provider for the Service does the authentication. 
     string retval = proxy.login("Logging in"); 

     //Now that channel is established the proxy needs to be kept 
     //since it contains the channel state which includes a private key 
     Session["MyServiceProxy"] = proxy; 
     Authenticated = true; 
    } 
    catch (Exception ex) 
    { 
     //Login Error... 
    } 
    e.Authenticated = Authenticated; 
} 
+0

Я думаю, что ваше предложение интересное, но меня беспокоит, что произойдет, если произошел сбой канала (ошибка связи, необработанное исключение службы и т. Д.) - сеанс веб-приложения будет содержать ссылку на мертвый прокси, и не было бы способа создайте новый прокси-сервер, так как у меня не будет доступа к паролю пользователя. –

+0

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

+0

Каждый раз, когда вы создаете экземпляр прокси, ему необходимо пройти рукопожатие, чтобы установить безопасный канал. В зависимости от конфигурации это может включать обмен сертификатами и создание и использование эфемерного ключа шифрования. Кэширование прокси-сервера устраняет этот обмен из-за каждого запроса. Я не уверен, как ответить на вопрос о неисправном канале, так как я не тестировал этот сценарий. Если он не будет автоматически восстановлен, вам, вероятно, потребуется также сохранить имя пользователя и пароль. Я не знаю, что у вас будет большой выбор. – RonnBlack

0

Я бы предложил взглянуть на Geneva, которая направлена ​​на решение сценариев, как ваша. Основная идея заключается в том, чтобы требовать один и тот же токен безопасности, как и HttpModule, как для служб WCF, так и для сайта ASP. Токен будет выпущен после проверки подлинности вашей базы данных членства и может содержать полезную информацию (претензии) для пользователя.

Для ознакомления с запросом Вы можете прочитать Bustamante's article.

+0

Я изучил Женеву в результате чтения статьи Bustamente пару месяцев назад, и это похоже на возможное решение, но оно все еще находится в стадии бета-тестирования, и, к сожалению, мне сейчас нужно решение. :-) –

0

Microsoft имеет службу WCF, которую вы можете использовать для аутентификации пользователей с членством в ASP.NET.

Код фактически встроен в структуру - вам просто нужно создать файл .svc для его использования.

http://msdn.microsoft.com/en-us/library/bb398990.aspx

Смежные вопросы