Создание локального кеша токенов с использованием Женевской платформы

StackOverflow https://stackoverflow.com/questions/400246

Вопрос

Я еще не видел много вопросов, связанных с Женевой, я разместил этот вопрос в Женевский форум также...

Я работаю над сценарием, в котором у нас есть приложение Win Forms с широкой базой установок, которое будет выполнять частые вызовы к различным службам, размещенным у нас централизованно на протяжении всей своей работы.

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

По умолчанию, используя ws2007FederationHttpBinding, приложение можно настроить на получение токена от STS перед каждым вызовом службы, но, очевидно, это не самый эффективный способ, поскольку мы почти дублируем усилия по вызову служб.

В качестве альтернативы я реализовал код, необходимый для получения токена «вручную» из приложения, а затем передал тот же предварительно полученный токен при вызове операций в службах (на основе примера WSTrustClient и справки на форуме);это работает хорошо, и поэтому у нас есть решение, но я считаю, что оно не очень элегантно, поскольку требует создания канала WCF в коде, отходя от замечательной конфигурации WCF.

Я предпочитаю подход ws2007FederationHttpBinding, при котором клиент просто вызывает службу, как и любую другую службу WCF, ничего не зная о Женеве, а привязки заботятся об обмене токенами.

Затем кто-то (Джон Симпсон) подал мне [как мне кажется] отличную идею — добавить службу, размещенную в самом приложении, для кэширования локально полученных токенов.Служба локального кэша будет реализовывать тот же контракт, что и STS;при получении запроса он проверит, существует ли кэшированный токен, и если да, вернет его, в противном случае он вызовет «настоящий» STS, получит новый токен, кэширует его и вернет.Тогда клиентское приложение по-прежнему могло бы использовать ws2007FederationHttpBinding, но вместо использования STS в качестве эмитента оно будет иметь локальный кеш;

Я думаю, что таким образом мы сможем достичь лучшего из обоих миров - кэширования токенов без специального кода, специфичного для службы;наш кеш должен иметь возможность обрабатывать токены для всех RP.

Я создал очень простой прототип, чтобы проверить, работает ли он, и - что, к сожалению, неудивительно - я немного застрял -

Моя локальная служба (в настоящее время консольное приложение) получает запрос и — впервые — вызывает STS для получения токена, кэширует его и успешно возвращает клиенту, который впоследствии использует его для вызова RP.все работает хорошо.

Однако во второй раз моя локальная служба кэширования пытается снова использовать тот же токен, но на стороне клиента происходит сбой с исключением 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;
Это было полезно?

Решение

Это почти неловко, но благодаря Доминику Байеру на форуме я теперь не понимаю, что упустил важный момент (я знал, что это не имеет смысла!честно!:-) ) -

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

Кроме того - я нашел очень интересный образец в образцах MSDN WCF - Поставщик долгосрочных выпущенных токенов, который, если я правильно понимаю, использует настраиваемое поведение конечной точки на стороне клиента для реализации кэширования токенов, что очень элегантно.

Я по-прежнему рассмотрю этот подход, поскольку у нас есть несколько сервисов, и мы могли бы добиться еще большей эффективности, повторно используя один и тот же токен между их прокси.

Итак - два решения, в значительной степени неочевидные для моих глаз;надеюсь, моя глупость кому-нибудь поможет!

Другие советы

Я предоставил полный пример кэширования токена здесь: http://blogs.technet.com/b/meamcs/archive/2011/11/20/caching-sts-security-token-with-an-active-web-client.aspx

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top