Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПвИ / Конспект лекций.doc
Скачиваний:
267
Добавлен:
01.06.2015
Размер:
1.05 Mб
Скачать

Пользовательские маркеры

Решение задачи идентификации пользователя возможно посредством использования маркера пользователя (UsernameToken), передаваемого на сторону Web-сервиса. В теле Web-метода осуществляется выделение маркера пользователя из SOAP-сообщения и производится анализ возможности запуска метода на исполнение (авторизация):

[WebMethod]

public string GetUserName()

{

SoapContext ctxt = RequestSoapContext.Current;

if(ctxt == null)

return "NON-SOAP request";

try

{

foreach(SecurityToken tok in ctxt.Security.Tokens)

if(tok is UsernameToken)

if(((UsernameToken)tok).Username != null)

return "Hello, " + ((UsernameToken)tok).Username.ToString();

}

catch(Exception e)

{

return "ServiceException on Service- " + e.Message.ToString();

}

return "Hello, Anonymous";

}

Клиентское приложение на своей стороне создает маркер пользователя и добавляет его в тело SOAP-сообщения:

UsernameToken userToken =

new UsernameToken(TextBox1.Text, TextBox2.Text,

PasswordOption.SendPlainText );

if(userToken == null)

{

Label2.Text = "userToken failed !";

return;

}

try

{

WSETestClient.localhost.Service1 s =

new WSETestClient.localhost.Service1();

SoapContext ctxt = s.RequestSoapContext;

if(ctxt == null)

{

Label2.Text = "NULL SoapContext pointer!";

return;

}

ctxt.Security.Timestamp.TtlInSeconds = 60;

ctxt.Security.Tokens.Add(userToken);

string userName = s.GetUserName();

Label1.Text = userName;

}

catch(System.Web.Services.Protocols.SoapException ex)

{

Label2.Text = "SoapException - " + ex.Message.ToString();

}

catch(Exception ex)

{

Label2.Text = "GeneralException - " + ex.Message.ToString();

}

Замечание: После создания ссылки на Web-сервис необходимо в определении класса прокси (файл Reference.cs) заменить родительский объект Web-сервиса на Microsoft.Web.Service2.WebServicesClientProtocol.

В данном примере есть один существенный недостаток – пароль пользователя передается в открытом виде. При описании способа передачи пароля (PasswordOption) имеется выбор среди следующих альтернатив:

Способ передачи

Описание

SendPlainText

Передача пароля в открытом виде

SendNone

Не передавать пароль

SendHashed

Передача хэш-значения пароля (хэш рассчитывается по схеме SHA-1)

Наиболее предпочтительной с точки зрения безопасности является альтернатива передачи хэш-значения пароля. Однако простое изменение свойства PasswordOption приводит к возникновению ошибки:

"The security token could not be authenticated or authorized."

(Маркер безопасности не может быть аутентифицирован или авторизован)

Передача пароля в открытом виде является серьезной уязвимостью в механизме взаимодействия клиента и Web-сервиса, однако такой способ передачи маркера безопасности позволяет Windows автоматически аутентифицировать пользователя, вызвав функцию LogonUser с соответствующими параметрами. В случае ошибки аутентификации генерируется программное исключение, а запрос метода Web-сервиса откланяется. При удачной авторизации WSE инициализирует свойство Principal из реквизитов UsernameToken.

Если пароль пользователя передается в виде хэш-значения, для успешной авторизации необходимо создать собственный обработчик поступающих вместе с SOAP-сообщениями маркеров безопасности. Для решения такой задачи создается новый класс, наследуемый от класса UsernameTokenManager, в котором выполняется переопределение метода AuthenticateToken. В методе AuthenticateToken выполняется сопоставление пароля и имени пользователя из маркера безопасности. Пароль пользователя затем передается инфраструктуре WSE. Перед возвратом пароля возможно создание объекта Principal:

Замечание: Пространство имен System.Security.Principal в библиотеке классов .NET Framework Class Library содержит объект Windows Principal, представляющий собой контекст защиты, в котором исполняется код.

На основе ролей можно создать универсальный объект Principal. Он применяется если есть собственная база данных пользователей и ролей. Одновременно можно задать идентификацию (identity).

public class MyUsernameTokenManager : UsernameTokenManager

{

protected override string AuthenticateToken(UsernameToken token)

{

if(token == null)

throw new ArgumentNullException();

switch(token.Username)

{

case "collegue":

token.Principal = new GenericPrincipal(

new GenericIdentity(token.Username),

new string[] {"Users"});

return "XXXXXXX";

default:

return base.AuthenticateToken (token);

}

}

}

Замечание: Использование нового класса обработки маркеров безопасности, порожденного от UsernameTokenManager, невозможно без изменения конфигурационного файла Web-сервиса (файла Web.config). Необходимо добавить в конфигурационный файл новый раздел <securityTokenManager> в блоке <microsoft.web.services2>:

<microsoft.web.services2>

.....

<security>

<securityTokenManager

type="WSETest1.MyUsernameTokenManager,

WSETest1"

xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"

qname="wsse:UsernameToken" />

</security>

</microsoft.web.services2>

Метод AuthenticateToken нового класса вызывается каждый раз при получении Web-сервисом SOAP-сообщения, в котором содержится маркер безопасности:

UsernameToken userToken =

new UsernameToken(TextBox1.Text, TextBox2.Text,

PasswordOption.SendHashed );

Таким образом, проблема передачи паролей решена. С другой стороны возникает вопрос: возможно ли подписывание передаваемых данных.

Соседние файлы в папке ПвИ