Пользовательский токен и Windows Identity Foundation - PullRequest
3 голосов
/ 21 декабря 2011

У меня есть веб-сервис, где я хочу получить авторизацию. Но для входа в систему пользователь должен указать имя пользователя, пароль и идентификатор своей компании. Стандартные классы аутентификации WCF поддерживают только имя пользователя и пароль, поэтому я решил создать пользовательские учетные данные с пользовательским токеном. Я вижу пример приложения токена от Microsoft ( wcf sample description ) и могу запустить его. Но сейчас настоящая проблема. На стороне сервера я хочу использовать Windows Identity Foundation (без STS - авторизация должна выполняться в пользовательском SecurityTokenHandler. Я создал этот обработчик:

public class MyCustomTokenHandler : SecurityTokenHandler
{
    public override string[] GetTokenTypeIdentifiers()
    {
        //this is invoked correctly
        return new string[] { Constants.CreditCardTokenNamespace };
    }
    public override Type TokenType
    {
        get
        {
            //this is invoked correctly
            return typeof(CreditCardToken);
        }
    }

    public override bool CanReadToken(XmlReader reader)
    {
        //this is invoked correctly
        if (reader.IsStartElement(Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace))
            return true;
        return false;
    }

    public override SecurityToken ReadToken(XmlReader reader)
    {
        //read token code - it is invoked correctly
    }

    public override bool CanValidateToken
    {
        get
        {//this is not invoked
            return true;
        }
    }

    public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
    {
        //this is not invoked
        IClaimsIdentity identity = new ClaimsIdentity();
        identity.Claims.Add(new Claim(WSIdentityConstants.ClaimTypes.Name, "Test"));

        return new ClaimsIdentityCollection(new IClaimsIdentity[] { identity });
    }
}

Для целей тестирования я создал второй обработчик, который наследуется от UserNameSecurityTokenHandler:

public class CustomUserNameSecurityTokenHandler : UserNameSecurityTokenHandler
{
    public override bool CanValidateToken
    {
        get
        {//this is invoked but it shouldn't!!!
            return true;
        }
    }

    public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
    {
        ...
    }
}

Я зарегистрировал их в web.config:

<microsoft.identityModel>
<service>
  <securityTokenHandlers>
    <remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add type="Microsoft.Samples.CustomToken.CustomUserNameSecurityTokenHandler, CreditCardToken"/>
    <add type="Microsoft.Samples.CustomToken.MyCustomTokenHandler, CreditCardToken"/>
  </securityTokenHandlers>     
</service>

Клиентское приложение отправляет мой CreditCardToken правильно (это клиент из примера приложения wcf). Но на стороне веб-сервиса у меня следующее поведение:

  1. TokenType и GetTokenTypeIdentifiers из MyCustomTokenHandler вызываются (хорошо)
  2. Методы CanReadToken и ReadToken из MyCustomTokenHandler вызываются (хорошо)
  3. Методы CanValidateToken и ValidateToken из MyCustomTokenHandler не вызываются (неправильно)
  4. Метод CanValidateToken из CustomUserNameSecurityTokenHandler вызывается (неверно, поскольку клиентское приложение отправило другой токен)
  5. В финале я получаю исключение:

Не удалось найти средство проверки подлинности токена для типа токена Microsoft.Samples.CustomToken.CreditCardToken. Токены этого типа не могут быть приняты в соответствии с текущими настройками безопасности.

В сообщении рассказывается об аутентификаторе токена для этого типа токена, но я знаю, что для этой цели используется обработчик токена из WIF.

Не могли бы вы сказать мне, что я должен сделать, чтобы заставить WIF использовать MyCustomTokenHandler для проверки (аутентификации)?

...