要做到这一点,我们有创建了一个ServiceFactory类,该类可连接到指定其端点的服务以及适当的接口。这假定你直接使用WCF服务,例如而不是通过VS生成的代理,因为您需要在每个客户端通道创建时设置用户名和密码值。
客户端通道接口与服务工厂一起位于外部“服务库”中,因此它们可以与WCF服务实现和客户端共享。我们将这些凭证存储在一个静态字典中(尽管您也将它放在主资源字典中),并将密码保存在SecuredString
中,以获得一点额外的安全性。
我所描述的基本过程为通过博客创建这样一个服务工厂:
http://blog.kutulu.org/2012/03/proxy-free-wcf-ditching-proxy.html
在我们的例子中,我们在App.xaml.cs
,对于凭据提示进行安装例程,使企图调用我们的服务之一,循环直到我们获得成功的登录。该代码要复杂得多,但它基本上是:
while (true)
{
var factory = new ChannelFactory<ITestChannel>(new WSHttpBinding("SecuredBinding"));
ITestChannel client = null;
try
{
factory.Credentials.UserName.UserName = logOnModel.UserName;
factory.Credentials.UserName.Password = logOnModel.Password;
var address = Settings.Default.TestServiceUrlBase));
client = factory.CreateChannel(address);
break;
}
// Catch various exceptions here.
}
在这里的技巧是,如果你的账号或密码是错误的,你UsernamePasswordValidator
无法登录,你会得到一个MessageSecurityException
将故障频道,所以你需要关闭它并打开一个新的。但是,一旦打开了第一个频道,您就无法更改ChannelFactory
上的凭据,因此您需要每次处理并重新创建新的工厂和新的客户端频道。
我们还在这里查询CommunicationException
和ArgumentException
以防万一网址错误。
完成之后,您可以在服务工厂类中使用类似的代码来构造客户端,并为其设置通道接口,并为每个调用设置凭据。 (我们实际上为每个不同的界面缓存服务工厂,因为我们频繁地创建和销毁频道,但这取决于您。)
在我们的案例中 - 客户端是使用Visual Studio的“添加服务引用”创建的。在调用'Open()'方法之前,凭证会传递给生成的客户端。所以 - 我不确定你的方法是否适合我的情况...... – 2012-07-09 13:44:53
你仍然可以使同一个想法奏效 - 一个创建你的频道的工厂类 - 它不会那么优雅。 VS服务引用确实为其底层客户端接口创建了一个“IClientChannel”接口,这可能有所帮助。或者你可以简单地为每个服务制定一个方法,如果这个数字足够小的话。 – 2012-07-09 13:57:28
我有4项服务。这够小吗?我只是无法理解它是如何连接的。所以我有一个'Service Clients'的DLL,其中有工厂,但是谁启动了它? 'LoginModel'?服务的实例存储在哪里? – 2012-07-09 14:00:48