Я еще не видел много вопросов, касающихся Женевы, я также разместил этот вопрос на Женевском форуме ...
Я работаю над сценарием, в котором у нас есть приложение win forms с широкой базой установки, которое будет отправлять частые звонки различным службам, размещенным нами централизованно на протяжении всей его работы.
Все службы используют Женевскую платформу, и все клиенты должны сначала позвонить в нашу STS, чтобы получить токен для доступа к услугам.
Из коробки, используя ws2007FederationHttpBinding, приложение можно настроить для получения токена из STS перед каждым вызовом службы, но, очевидно, это не самый эффективный способ, поскольку мы почти дублируем усилия по вызову служб .
В качестве альтернативы, я реализовал код, необходимый для извлечения токена «вручную» из приложения, а затем для передачи того же токена, предварительно полученного при вызове операций со службами (на основе примера WSTrustClient и справки на форуме); это работает хорошо, и поэтому у нас есть решение, но я считаю, что оно не очень элегантно, так как требует построения канала WCF в коде, отходя от прекрасной конфигурации WCF.
Я очень предпочитаю подход ws2007FederationHttpBinding, когда клиент просто вызывает службу, как любая другая служба WCF, ничего не зная о Женеве, а привязки заботятся об обмене токенами.
Затем кто-то (Джон Симпсон) дал мне [что я думаю] прекрасную идею - добавить службу, размещенную в самом приложении, для кэширования локально полученных токенов.
Служба локального кэша будет реализовывать тот же контракт, что и STS; при получении запроса он проверяет, существует ли привязанный токен, и если да, то возвращает его, в противном случае он вызывает «реальный» STS, извлекает новый токен, кэширует его и возвращает.
Тогда клиентское приложение может по-прежнему использовать ws2007FederationHttpBinding, но вместо STS в качестве эмитента оно будет иметь локальный кеш;
Таким образом, я думаю, что мы можем достичь лучшего из обоих миров - кэширование токенов без специального сервисного кода; наш кеш должен иметь возможность обрабатывать токены для всех RP.
Я создал очень простой прототип, чтобы посмотреть, работает ли он, и - что не удивительно, к сожалению, - я немного застрял -
Моя локальная служба (в настоящее время консольное приложение) получает запрос и - впервые - вызывает STS для получения токена, кэширует его и успешно возвращает его клиенту, который впоследствии использует его для вызова RP. все работает хорошо.
Однако во второй раз моя локальная служба cahce пытается снова использовать тот же токен, но на стороне клиента возникает ошибка MessageSecurityException -
"Обработчику безопасности не удалось найти заголовок безопасности в сообщении. Это может быть связано с тем, что сообщение является незащищенной ошибкой или из-за несоответствия связывающих сторон. Это может произойти, если служба настроена для обеспечения безопасности и клиент не использует безопасность. "
Что-то мешает использовать один и тот же токен более одного раза? Я сомневаюсь в этом, потому что, когда я повторно использовал токен согласно образцу WSTrustClient, он работал хорошо; что мне не хватает? моя идея возможна? хороший?
Вот (очень простые, на данном этапе) биты основного кода локального кэша -
static LocalTokenCache.STS.Trust13IssueResponse cachedResponse = null;
public LocalTokenCache.STS.Trust13IssueResponse Trust13Issue(LocalTokenCache.STS.Trust13IssueRequest request)
{
if (TokenCache.cachedResponse == null)
{
Console.WriteLine("cached token not found, calling STS");
//create proxy for real STS
STS.WSTrust13SyncClient sts = new LocalTokenCache.STS.WSTrust13SyncClient();
//set credentials for sts
sts.ClientCredentials.UserName.UserName = "Yossi";
sts.ClientCredentials.UserName.Password = "p@ssw0rd";
//call issue on real sts
STS.RequestSecurityTokenResponseCollectionType stsResponse = sts.Trust13Issue(request.RequestSecurityToken);
//create result object - this is a container type for the response returned and is what we need to return;
TokenCache.cachedResponse = new LocalTokenCache.STS.Trust13IssueResponse();
//assign sts response to return value...
TokenCache.cachedResponse.RequestSecurityTokenResponseCollection = stsResponse;
}
else
{
}
//...and reutn
return TokenCache.cachedResponse;