Чтение ClientCredentials из узла тела SOAP-запроса и проверка его в соответствии с Custom Validator? - PullRequest
1 голос
/ 06 июня 2011

У меня есть метод GetColors, который принимает GetColorIdsRQ в качестве параметра и возвращает GetColorIdsRS. GetColorIdsRQ - это SOAP-запрос, а GetColorIdsRS - это SOAP-Resposne. Вот детали реализации каждого из них:

GetColorIdsRQ:

[DataContract]
public class GetColorIdsRQ
{
    [DataMember(Name="UserCredentials",Order=0,IsRequired=true)]
    public UserCredentials UserCredentials { get; set; }
}

UserCredentials:

[DataContract(Name="UserCredentials")]
public class UserCredentials
{
    [DataMember(Name="Username",Order=0,IsRequired=true)]
    public string UserName { get; set; }
    [DataMember(Name="Password",Order=1,IsRequired=true)]
    public string Password { get; set; }
}

GetColorIdsRS:

[DataContract]
public class GetColorIdsRS
{
    [DataMember(Name = "ColorsIds", IsRequired = true, Order = 0)]
    public List<Color> ColorIds { get; set; }
}

Цвет:

[DataContract(Name="Color")]
public class Color    
{
   [DataMember(Name="Code",IsRequired=true,Order=0)]
   public string Code { get; set; }
   [DataMember(Name="Name",IsRequired=true,Order=1)]
   public string Name { get; set; }  
}

Вот как метод является объявлением в интерфейсе:

[OperationContract(Name = "GetColorIds")]
GetColorIdsRS GetColorsIds(GetColorIdsRQ req);

Это реализация GetColorIds:

public GetColorIdsRS GetColors(GetColorIdsRQ req)
{
    GetColorIdsRS getColorIdsRS = new GetColorIdsRS();
    List<Color> colorIds = new List<Color>();

    req.UserCredentials.UserName = "test";
    req.UserCredentials.Password = "test";

    //Validate Username and Password

    DataTable dtColorIds = Data.GetDataTable("GetColors");

    foreach (DataRow item in dtColorIds.Rows)
    {
        colorIds.Add(new Color { Name = item["Name"].ToString(), 
                                 Code = item["ColorId"].ToString() });
    }

    getColorIdsRS.ColorIds = colorIds;

    return getColorIdsRS;
}

Когда я вызываю GetColors из тестового клиента WCF, тело запроса:

<s:Body>
    <GetColors xmlns="http://test.com/2011/05">
      <req xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
       <UserCredentials>
         <Username>test</Username>
         <Password>test2</Password>
       </UserCredentials>
     </req>
   </GetColors>
 </s:Body>

Проблема с вышесказанным заключается в том, что я хочу использовать Username и Password узлы для CustomUserNameValidator. Я не уверен, как заставить CustomUserNameValidator распознать узлы GetColorIdsRQ Имя пользователя и Пароль, чтобы он мог это проверить. Если вы заметили выше в методе GetColors, я устанавливаю:

req.UserCredentials.UserName = "test";
req.UserCredentials.Password = "test";

но это не подтверждается, очевидно. Вот реализация моего CustomUserNamePasswordValidator:

public class CustomUserNameValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // check if the user is not test
        if (userName != "test" || password != "test")
            throw new FaultException("Username and Password Failed");
    }
}

По сути, если я пройду:

req.UserCredentials.UserName = "test";
req.UserCredentials.Password = "test2";

CustomUserNameValidator должен выдавать исключение FaultException.

Обратите внимание, что в методе GetColors у меня есть комментарий "// Подтвердить имя пользователя и пароль", я знаю, что могу сделать:

CustomUserNameValidator val = new CustomUserNameValidator();
val.Validate(req.UserCredentials.UserName,req.UserCredentials.Password)

и выше будет вызывать метод Validate, но я знал, что он должен быть автоматическим, и тогда мне придется делать это в каждом отдельном методе.

Правда ли, что единственный способ вызова CustomUserNameValidator - это установить ClientCredentials в прокси-коде, например:

proxy.ClientCredentials.UserName.UserName = "test;
proxy.ClientCredentials.UserName.Password = "test;

Вышеуказанное вызовет вызов метода Validate, но если я не смогу выполнить вышеизложенное, и я установил имя пользователя и пароль в качестве свойств объекта Request, тогда Validate вызываться не будет, поэтому мой другой вариант просто иметь свой собственный метод Validate в каждой операции, которая требует его. Операция не будет вызываться в случае сбоя ClientCredentials, но в моем случае мне нужно вызвать операцию, а затем вернуть ответ SOAP с узлом ошибки с чем-то вроде «Неверное имя пользователя и / или пароль» вместо броска исключение FaultException.

Исходя из вышеизложенного, лучше ли избегать использования CustomUserNamePasswordValidator в моем случае?

В случае, если имя пользователя и пароль не могут быть установлены с помощью учетных данных клиента прокси, а скорее отправлены через тело запроса мыла, тогда кажется, что способ справиться с этим - обработать проверку в операционной и влияет ли это на параметры безопасности (например, есть ли точка для clientCredentialType = "Username")

1 Ответ

0 голосов
/ 06 июня 2011

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

Почему вы не используете стандартную аутентификацию UserName?

Edit:

Если вы хотите передать учетные данные в пользовательском элементе в теле сообщения (и вы не будете изменять конвейер безопасности), проверка зависит от вас - она ​​не будет перенаправлена ​​на валидатор имени пользователя. Вы должны сделать это либо в действии, либо вы можете создать собственный инспектор сообщений (реализовать IMessageInspector) и обернуть его пользовательским поведением конечной точки (IEndpointBehavior), чтобы централизовать проверку.

...