У меня есть веб-сервис, где я хочу получить авторизацию. Но для входа в систему пользователь должен указать имя пользователя, пароль и идентификатор своей компании. Стандартные классы аутентификации 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). Но на стороне веб-сервиса у меня следующее поведение:
- TokenType и GetTokenTypeIdentifiers из MyCustomTokenHandler вызываются (хорошо)
- Методы CanReadToken и ReadToken из MyCustomTokenHandler вызываются (хорошо)
- Методы CanValidateToken и ValidateToken из MyCustomTokenHandler не вызываются (неправильно)
- Метод CanValidateToken из CustomUserNameSecurityTokenHandler вызывается (неверно, поскольку клиентское приложение отправило другой токен)
- В финале я получаю исключение:
Не удалось найти средство проверки подлинности токена для типа токена Microsoft.Samples.CustomToken.CreditCardToken. Токены этого типа не могут быть приняты в соответствии с текущими настройками безопасности.
В сообщении рассказывается об аутентификаторе токена для этого типа токена, но я знаю, что для этой цели используется обработчик токена из WIF.
Не могли бы вы сказать мне, что я должен сделать, чтобы заставить WIF использовать MyCustomTokenHandler для проверки (аутентификации)?