Using Windsor Castle and WcfFacility to create WCF proxies with Message Security and username credentials
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 = n开发者_如何学运维ew 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
}
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.
Your credentials and IWcfEndpoint
in general (which is the result of DefaultClientModel.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:
_container.Register(Component.For<IFrameworkUsers>()
.AsWcfClient()
.DependsOn(
(k, d) => d["endpoint"] =
new DefaultClientModel(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
.Credentials(new CustomCredentials())
)
.LifeStyle.Transient);
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 of AsWcfClient(IWcfEndpoint endpoint)
method argument.
So the answer is no, it is nor bug nor limitation of WcfFacility.
精彩评论