使用 Windsor Castle 和 WcfFacility 创建具有 Message Security 和用户名凭据的 WCF 代理
好的,我们正在使用消息安全和用户名凭据(以及 X509 证书加密)来与我们的 WCF 服务进行通信。我对这种方法不满意,但这不是问题的重点,我不想讨论这个问题。
我正在使用温莎城堡在ASP NET Web Forms + MVC 混合中生成代理。我们正在使用表单身份验证并使用用户的凭据与 WCF 服务进行通信 - 这将有助于审核所有调用。正如我所说,我对这种方法不满意,但这不是重点。
我创建了继承 AbstractCredentials 类的 CustomCredentials 类,并且 WcfFacility 很乐意使用它来配置我的代理。正如您将在下面看到的,我的所有设置都只有几行。我在下面创建了单元测试,它演示了我正在做的所有事情:创建代理,进行调用,然后在循环中释放它。现在我期望这个测试能够工作,但它没有工作,我得到
Expected: 10 But was: 1
我没有包含绑定,但这无关紧要,正如我所说的,我正在将 Message Security 与 X509 证书一起使用。
我知道对于具有消息安全性的通道工厂,一旦打开就无法更改凭据。这是同一个问题吗?
这是 WcfFacility 中的错误还是限制?
这是代码
[TestFixture]
public class Harness
{
private IWindsorContainer _container;
public static int NumberOfTimesCredentialsConfigured = 0;
[SetUp]
public void Setup()
{
_container = new WindsorContainer().AddFacility<WcfFacility>();
Component
.For<IFrameworkUsers>()
.ActAs(DefaultClientModel
.On(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
.Credentials(new CustomCredentials()))
.LifeStyle.Transient);
}
[Test]
public void MultipleProxyTest()
{
const int Runs = 10;
NumberOfTimesCredentialsConfigured = 0;
for (int i = 0; i < Runs; i++)
{
IFrameworkUsers frameworkUsers = _container.Resolve<IFrameworkUsers>();
frameworkUsers.CreateUserSession();
_container.Release(frameworkUsers);
}
Assert.AreEqual(Runs, NumberOfTimesCredentialsConfigured);
// FAILS!!! Expected: 10 But was: 1
}
[TearDown]
public void TearDown()
{
}
}
public class CustomCredentials : AbstractCredentials
{
#region Overrides of AbstractCredentials
protected override void ConfigureCredentials(ClientCredentials credentials)
{
credentials.UserName.UserName = "testuser";
credentials.UserName.Password = "abcdef";
Harness.NumberOfTimesCredentialsConfigured++;
}
#endregion
}
OK we are using message security with username credentials (and X509 certificate encryption) to communicate with our WCF service. I am not happy with this approach but that is not the point of question and I do not want to get into that.
I am using Windsor Castle to generate proxies in ASP NET Web Forms + MVC hybrid. We are using forms authentication and use user's credentials to communicate with WCF services - this will help auditing all calls. As I said, I am not happy with this approach but that is not the point.
I have created CustomCredentials
class which inherits AbstractCredentials
class and WcfFacility happily uses it to configure my proxies. As you will see below, all my setup is just a few lines. I have created unit test below which demonstrates all I am doing: creating a proxy, making a call and then releasing it in a loop. Now I am expecting this test to work but it does not and I get
Expected: 10 But was: 1
I have not included binding but that is irrelevant, as I said I am using Message Security with X509 certificates.
I know that for channel factory with message security, once opened you cannot change credentials. Is this the same issue?
Is this a bug in WcfFacility or a limitation?
Here is the code
[TestFixture]
public class Harness
{
private IWindsorContainer _container;
public static int NumberOfTimesCredentialsConfigured = 0;
[SetUp]
public void Setup()
{
_container = new WindsorContainer().AddFacility<WcfFacility>();
Component
.For<IFrameworkUsers>()
.ActAs(DefaultClientModel
.On(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
.Credentials(new CustomCredentials()))
.LifeStyle.Transient);
}
[Test]
public void MultipleProxyTest()
{
const int Runs = 10;
NumberOfTimesCredentialsConfigured = 0;
for (int i = 0; i < Runs; i++)
{
IFrameworkUsers frameworkUsers = _container.Resolve<IFrameworkUsers>();
frameworkUsers.CreateUserSession();
_container.Release(frameworkUsers);
}
Assert.AreEqual(Runs, NumberOfTimesCredentialsConfigured);
// FAILS!!! Expected: 10 But was: 1
}
[TearDown]
public void TearDown()
{
}
}
public class CustomCredentials : AbstractCredentials
{
#region Overrides of AbstractCredentials
protected override void ConfigureCredentials(ClientCredentials credentials)
{
credentials.UserName.UserName = "testuser";
credentials.UserName.Password = "abcdef";
Harness.NumberOfTimesCredentialsConfigured++;
}
#endregion
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我在城堡论坛发帖了,没有回复。这是 WCF 设施中设计的一个问题,它们在其中缓存服务通道,这些通道在没有安全性的情况下可以使用,但在安全性的情况下不起作用。
I posted on castle forum and no reply. It is a problem by design in WCF Facility in which they cache service channels which is OK with no security but does not work with security.
通常,您的凭据和
IWcfEndpoint
(这是DefaultClientModel.On(...)
调用的结果)仅在配置容器时创建一次。如果您想每次提供不同的凭据 - 您需要使它们成为动态依赖项,如下所示:String
endpoint
这里是 WcfFacility 使用的依赖项的名称。我不确定具体在哪里,但它在某些拦截器中得到了解决(您可以在 lambda 中设置断点并调试测试以查看调用堆栈)。我假设它是为了匹配AsWcfClient(IWcfEndpoint endpoint)
方法参数的名称。所以答案是否定的,这不是 WcfFacility 的错误或限制。
Your credentials and
IWcfEndpoint
in general (which is the result ofDefaultClientModel.On(...)
call) are created only once when the container is configured. If you want to provide different credentials each time - you need to make them dynamic dependency like below:String
endpoint
here is the name of dependency consumed by WcfFacility. I'm not sure where exactly, but it is resolved in some interceptor (you may set breakpoint in the lambda and debug your test to look at call stack). I assume it is made to match name ofAsWcfClient(IWcfEndpoint endpoint)
method argument.So the answer is no, it is nor bug nor limitation of WcfFacility.