Visual Studio - 在 WCF 中设置客户端凭据时出现"Object is read only"错误



我有一个由Visual Studio(客户端)生成的名为ServerClient的代理对象。我正在尝试设置ClientCredentials。用户名。使用以下代码打开新连接之前的用户名/密码:

InstanceContext context = new InstanceContext(this);
m_client = new ServerClient(context);
m_client.ClientCredentials.UserName.UserName = "Sample";

一旦代码到达UserName行,它就会失败,并显示"Object is read-only"错误。我知道如果连接已经打开或出现故障,可能会发生这种情况,但目前我还没有调用上下文。打开()。

我已将Bindings(使用netTcpBinding)配置为使用Message作为其安全模式,并且MessageClientCredentialType设置为UserName。

有什么想法吗?

我注意到,在为服务创建代理类的实例后,我可以毫无错误地设置一次用户名和密码,并成功调用我的Web服务。当我尝试在现有实例上再次设置用户名和密码时(当然没有必要),我会收到你提到的"对象是只读的"错误。每个实例生命周期设置一次值对我来说很有效。

似乎只能在通知周期的早期访问这些属性。如果我覆盖代理类(ServerClient)中的构造函数,我就可以设置以下属性:

base.ClientCredentials.UserName.UserName = "Sample";

我开始感谢那些建议不要使用VS提供的自动构建的代理的人。

这里是解决方案:

using SysSvcmod = System.ServiceModel.Description;
SysSvcmod.ClientCredentials clientCredentials = new SysSvcmod.ClientCredentials();
clientCredentials.UserName.UserName = "user_name";
clientCredentials.UserName.Password = "pass_word";
m_client.ChannelFactory.Endpoint.Behaviors.RemoveAt(1);
m_client.ChannelFactory.Endpoint.Behaviors.Add(clientCredentials);

我有类似的代码正在传递UserName fine:

  FooServiceClient client = new FooServiceClient("BasicHttpBinding_IFooService");
  client.ClientCredentials.UserName.UserName = "user";
  client.ClientCredentials.UserName.Password = "password";

尝试在app.config中创建具有绑定名称的代理。

正确的语法是:

// Remove the ClientCredentials behavior.
client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
// Add a custom client credentials instance to the behaviors collection.
client.ChannelFactory.Endpoint.Behaviors.Add(new MyClientCredentials());

http://msdn.microsoft.com/en-us/library/ms730868.aspx

它对我有效。

我也遇到了同样的问题,当我更改代码时,我的代码开始工作,即在初始化客户端对象后立即将值分配给客户端凭据。

这是的解决方案

ProductClient Manager = new  ProductClient();    
Manager.ClientCredentials.UserName.UserName = txtUserName.Text;
Manager.ClientCredentials.UserName.Password = txtPassword.Text;

如果通过->添加服务引用->高级->添加Web引用->Url/wsdl(本地磁盘文件)添加服务引用,则不会发生这种情况。

我遇到了这个问题,我试图创建一个通用方法来为不同的端点创建客户端。

以下是我是如何做到这一点的。

    public static T CreateClient<T>(string url) where T : class
    {
        EndpointAddress endPoint = new EndpointAddress(url);
        CustomBinding binding = CreateCustomBinding();
        T client = (T)Activator.CreateInstance(typeof(T), new object[] { binding, endPoint });
        SetClientCredentials(client);
        return client;
    }
    public static void SetClientCredentials(dynamic obj)
    {
        obj.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
        obj.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
        obj.ClientCredentials.UserName.UserName = "UserId";
        obj.ClientCredentials.UserName.Password = "Password";
    }

我认为您的问题可能与InstanceContext的使用有关。我认为这只需要用于服务器端的双工通信信道。

我承认我对此不确定,但我认为在这种情况下,你是在告诉客户端使用现有的实例上下文,所以它认为已经有一个正在运行的服务,不允许更改。

是什么推动了InstanceContext的使用?

如果使用双工客户端,当您实例化它时,从中派生客户端的DuplexClientBase中的DuplexChannelFactory将使用现有凭据进行初始化,这样它就可以打开回调通道,这就是为什么凭据将是只读的。

我支持Mike的问题,并问如果您不打算使用NetTcpBinding固有的传输级别安全性,为什么要使用它?也许基于HTTP的绑定更适合?这将允许您使用基于证书的安全性,我相信可以在实例化后进行修改(http://msdn.microsoft.com/en-us/library/ms576164.aspx)。

这是在黑暗中拍摄的,但netTcpBinding允许用户名和密码验证吗?尝试使用http绑定来使用应用层(SOAP)安全性

或者您可以简单地检查凭证

    if (client.ClientCredentials.ClientCertificate.Certificate == null || string.IsNullOrEmpty(client.ClientCredentials.ClientCertificate.Certificate.Thumbprint))
    {
        client.ClientCredentials.ClientCertificate.SetCertificate(
            StoreLocation.LocalMachine,
            StoreName.My,
            X509FindType.FindByThumbprint, ConfigurationManager.AppSettings.Get("CertificateThumbprint"));
    }

In。NET 4.6我无法使用Fabienne的答案删除凭据。一直在Remove方法中获取编译器错误CS0308。对我有效的是:

Type endpointBehaviorType = serviceClient.ClientCredentials.GetType();
serviceClient.Endpoint.EndpointBehaviors.Remove(endpointBehaviorType);
ClientCredentials clientCredentials = new ClientCredentials();
clientCredentials.UserName.UserName = userName;
clientCredentials.UserName.Password = password;
serviceClient.Endpoint.EndpointBehaviors.Add(clientCredentials);

相关内容

最新更新