Создание локального кэша токенов с использованием Geneva Framework - PullRequest
5 голосов
/ 30 декабря 2008

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

Я работаю над сценарием, в котором у нас есть приложение 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;

Ответы [ 2 ]

6 голосов
/ 30 декабря 2008

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

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

Кроме того, я обнаружил очень интересный пример на примере MSDN WCF. Durable Issued Token Provider , который, если я правильно понимаю, использует настраиваемое поведение конечной точки на стороне клиента для реализации кэширования токенов. , что очень элегантно.

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

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

1 голос
/ 20 ноября 2011

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

...