还没有看到很多与日内瓦相关的问题,我已经将这个问题发布在 日内瓦论坛 还有...

我正在研究一个场景,我们有一个具有广泛安装基础的 win forms 应用程序,它将在整个操作过程中频繁调用我​​们集中托管的各种服务。

这些服务均使用日内瓦框架,所有客户都应首先调用我们的 STS,以便获得令牌以允许访问服务。

开箱即用,使用 ws2007FederationHttpBinding,应用程序可以配置为在每次服务调用之前从 STS 检索令牌,但显然这不是最有效的方法,因为我们几乎重复了调用服务的工作。

或者,我已经实现了从应用程序“手动”检索令牌所需的代码,然后在调用服务操作时传递相同的预检索令牌(基于 WSTrustClient 示例和论坛上的帮助);效果很好,所以我们确实有一个解决方案,但我相信它不是很优雅,因为它需要在代码中构建 WCF 通道,远离美妙的 WCF 配置。

我更喜欢 ws2007FederationHttpBinding 方法,客户端只需像任何其他 WCF 服务一样调用该服务,而无需了解有关Geneva的任何信息,并且绑定负责令牌交换。

然后有人(乔恩·辛普森)给了我[我认为]一个好主意 - 添加一个托管在应用程序本身中的服务来缓存本地检索的令牌。本地缓存服务将实现与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;
有帮助吗?

解决方案

这几乎令人尴尬,但多亏了论坛上的 Dominick Baier,我现在没有意识到我错过了一个重要的点(我知道这没有意义!诚实地!:-) ) -

每个服务代理都会检索一次令牌,假设它没有过期,所以我需要做的就是重用同一个代理,无论如何我都计划这样做,但相当愚蠢的是,我的原型上没有这样做。

另外——我在MSDN WCF样本上发现了一个非常有趣的样本—— 持久发行代币提供商, ,如果我理解正确的话,它在客户端使用自定义端点行为来实现令牌缓存,这是非常优雅的。

我仍然会考虑这种方法,因为我们有多种服务,因此我们可以通过在代理之间重复使用相同的令牌来实现更高的效率。

所以 - 两种解决方案,几乎是我的眼睛的信息;希望我的愚蠢能在某个时候帮助别人!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top