我在處理以下場景中遇到了相當大的挑戰。如何引導使用Unity InjectionFactory創建的WCF通道的securitytoken
- 我想在需要時使用Unity DI Framework爲我的服務創建一個新通道。
- 該服務通過聯合安全進行保護。
- 服務不是從託管在IIS中的服務中調用的,而是從自託管的WCF服務中調用的。
我目前的問題發生在上面的第3步 - 我如何引導令牌,然後滿足上述2的要求?我將概述每個步驟的解決方案,因爲它們不重要,並且希望可以幫助其他人解決此問題。
解決問題1: 下面的代碼片段將隨時創建一個新的渠道實例。
container.RegisterType<IMyWcfService>(new PerResolveLifetimeManager(),
new InjectionFactory(
x => new ChannelFactoryWithChannelFactoryOperations<IMyWcfService>("*")
.CreateChannel()));
這裏的人在做這更好的一些例子比我: http://unity.codeplex.com/discussions/211736 https://gist.github.com/tracker1/5675161
您還可以使用替代一生經理以及如TransientLifetimeManager在這裏可以很好地工作。
解決問題2: 現在真正的困難開始了 - 我如何在InjectionFactory中包含安全令牌? 很明顯,我打算使用CreatChannelWithIssuedToken,但我需要抓取引導令牌來執行此操作。這在網絡周圍有相當好的記錄,例如,在這裏: http://www.cloudidentity.com/blog/2012/11/30/using-the-bootstrapcontext-property-in-net-4-5-2/ 一些重要的事情要注意:確保你有一個serviceBehaviors部分在配置中指定useIdentityConfiguration =「true」,否則你的system.identityModel部分將被忽略,例如,
<serviceBehaviors>
<behavior name="">
<serviceCredentials useIdentityConfiguration="true" />
</behavior>
</serviceBehaviors>
然後你的系統。identityModel部分還應配備:
<system.identityModel>
<identityConfiguration>
<securityTokenHandlers>
<securityTokenHandlerConfiguration saveBootstrapContext="true" />
</securityTokenHandlers>
</identityConfiguration>
</system.identityModel>
然後,只要你做對會話正確設置此(見我的其他問題的請求:AJAX call against REST endpoint secured with Thinktecture's IdentityServer STS將可在會話每當你訪問的引導上下文安全令牌像這樣:
var bootstrapContext = ((ClaimsIdentity) Thread.CurrentPrincipal.Identity).BootstrapContext
as BootstrapContext;
SecurityToken securityToken = bootstrapContext.SecurityToken;
然後,您可以更改您的InjectionFactory看起來像這樣:
container.RegisterType<IControllerConfigurationService>(new PerResolveLifetimeManager(),
new InjectionFactory(
x =>
{
var bootstrapContext = ((ClaimsIdentity)
Thread.CurrentPrincipal.Identity).BootstrapContext as BootstrapContext;
var securityToken = bootstrapContext.SecurityToken;
return new ChannelFactoryWithChannelFactoryOperations<IMyWcfService>("*")
.CreateChannelWithIssuedToken(securityToken);
}));
或每HAPS更好的是,創建一個自ChannelFactory繼承的類,並補充說,拉結合上述邏輯到單個CreateChannelWithIssuedTokenUsingBootstrapContext方法的方法:
public class ChannelFactoryWithChannelFactoryOperations<T> : ChannelFactory<T>
{
protected ChannelFactoryWithChannelFactoryOperations(Type channelType) : base(channelType)
{
}
public ChannelFactoryWithChannelFactoryOperations()
{
}
public ChannelFactoryWithChannelFactoryOperations(string endpointConfigurationName)
: base(endpointConfigurationName)
{
}
public ChannelFactoryWithChannelFactoryOperations(string endpointConfigurationName,
EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress)
{
}
public ChannelFactoryWithChannelFactoryOperations(Binding binding) : base(binding)
{
}
public ChannelFactoryWithChannelFactoryOperations(Binding binding, string remoteAddress)
: base(binding, remoteAddress)
{
}
public ChannelFactoryWithChannelFactoryOperations(Binding binding, EndpointAddress remoteAddress)
: base(binding, remoteAddress)
{
}
public ChannelFactoryWithChannelFactoryOperations(ServiceEndpoint endpoint) : base(endpoint)
{
}
public T CreateChannelWithIssuedTokenUsingBootstrapContext()
{
var bootstrapContext =
((ClaimsIdentity) Thread.CurrentPrincipal.Identity).BootstrapContext as BootstrapContext;
SecurityToken securityToken = bootstrapContext.SecurityToken;
return CreateChannelWithIssuedToken(securityToken);
}
}
這可以讓你那麼只需要調用此:
container.RegisterType<IMyWcfService>(new PerResolveLifetimeManager(),
new InjectionFactory(
x => new ChannelFactoryWithChannelFactoryOperations<IMyWcfService>("*")
.CreateChannelWithIssuedTokenUsingBootstrapContext()));
解決問題3: 添加上述兩個問題的複雜性後,我現在在自己的自託管WCF服務中嘗試在IIS之外使用同樣的東西。這個相同的服務是完全無狀態的,所以這裏是我的下一個難題發生的地方: 安全令牌的引導仍然存在,但它不在正確的線程上發生。 Unity似乎在一個單獨的Thread中將其InjectionFactory運行到實際的服務調用執行。
即當上面的InjectionFactory委託執行時,CurrentPrincipal是未授權的GenericPrincipal。這與我們在上面問題2中得到的不同 - 它是授權的ClaimsPrincipal - 我相信這全部由IIS會話設置(如果我不正確,請隨時糾正)。
有趣的是,如果我們再更換以上
container.RegisterType<IMyWcfService>(new PerResolveLifetimeManager(),
new InjectionFactory(
x => new ChannelFactoryWithChannelFactoryOperations<IMyWcfService>("*")
.CreateChannel()));
即現在只是注入一個不安全的通道對象,我們可以看到,在我們的自承載WCF服務,我們真正嘗試與互動通道,Thread.CurrentPrincipal是經過身份驗證的ClaimsPrincipal,其中SecurityToken在主體上正確引導。
所以這個問題可以概括如下: 因爲InjectionFactory委託在還沒有發生認證/授權的線程上執行,所以SecurityToken實際上並不可用於傳遞給通道的創建。
有沒有人對我如何解決這個問題有任何建議?我是否已經將自己託管的WCF和團結的這種特殊組合融合到了一個角落?
感謝, 克林特