在 App.config 中设置 WCF ClientCredentials

Posted

技术标签:

【中文标题】在 App.config 中设置 WCF ClientCredentials【英文标题】:Set WCF ClientCredentials in App.config 【发布时间】:2011-04-13 02:56:47 【问题描述】:

是否可以在 App.config 中为 WCF 设置客户端凭据?

我想避免这样做:

Using svc As New MyServiceClient
  svc.ClientCredentials.UserName.UserName = "login"
  svc.ClientCredentials.UserName.Password = "pw"

  ...
End Using

登录名和密码应该是配置的一部分。

【问题讨论】:

【参考方案1】:

这就是我为使新的身份验证工作所做的工作

进一步扩展 Mormegil's answer 这是如何使用 customBehavior 实现。

public class UserNameClientCredentialsElement : ClientCredentialsElement
 // class renamed only to follow the configuration pattern
   ... // using Mormegil's implementation

之后您需要:

    注册行为扩展。 使用配置扩展定义一个新的行为配置。 (这是棘手的部分,关于如何做到这一点的报道很少。) 将配置应用到端点。

使用类似的东西:

<system.serviceModel>
  <client><!--(3)-->
    <endpoint ...YourEndpointConfig... behaviorConfiguration="UserNamePasswordBehavior" />
  </client>
  <behaviors><!--(2)-->
    <endpointBehaviors>
      <behavior name="UserNamePasswordBehavior">
        <userNameClientCredentials userName="skroob" password="12345" />
        <!--Visual Studio will give you warning squiggly on <userNameClientCredentials>
            saying that "The element 'behavior' has invalid child element" 
            but will work at runtime.-->
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <extensions><!--(1)-->
    <behaviorExtensions>
      <add name="userNameClientCredentials" type="MyNamespace.UserNameClientCredentialsElement, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>
  ...
</system.serviceModel>

【讨论】:

【参考方案2】:

扩展 Ladislav Mrnka 的答案,您可能会发现此实现很有用:

public class UserNameClientCredentials : ClientCredentialsElement

    private ConfigurationPropertyCollection properties;

    public override Type BehaviorType
    
        get  return typeof (ClientCredentials); 
    

    /// <summary>
    /// Username (required)
    /// </summary>
    public string UserName
    
        get  return (string) base["userName"]; 
        set  base["userName"] = value; 
    

    /// <summary>
    /// Password (optional)
    /// </summary>
    public string Password
    
        get  return (string) base["password"]; 
        set  base["password"] = value; 
    

    protected override ConfigurationPropertyCollection Properties
    
        get
        
            if (properties == null)
            
                ConfigurationPropertyCollection baseProps = base.Properties;
                baseProps.Add(new ConfigurationProperty(
                                  "userName",
                                  typeof (String),
                                  null,
                                  null,
                                  new StringValidator(1),
                                  ConfigurationPropertyOptions.IsRequired));
                baseProps.Add(new ConfigurationProperty(
                                  "password",
                                  typeof (String),
                                  ""));
                properties = baseProps;
            
            return properties;
        
    

    protected override object CreateBehavior()
    
        var creds = (ClientCredentials) base.CreateBehavior();
        creds.UserName.UserName = UserName;
        if (Password != null) creds.UserName.Password = Password;
        ApplyConfiguration(creds);
        return creds;
    

之后,您需要使用类似的方式注册此自定义实现

<system.serviceModel>
  <extensions>
    <behaviorExtensions>
      <add name="UserNameClientCredentials" type="MyNamespace.UserNameClientCredentials, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>
...

【讨论】:

谢谢,它看起来是一个非常简洁的实现。有一天我会试试的。 :)【参考方案3】:

您可以尝试继承ClientCredentialsElement(处理默认配置部分)并添加对用户名和密码的支持。您可以在配置文件中将此元素注册为行为扩展,并使用它来代替通用配置部分。

【讨论】:

【参考方案4】:

据我所知,使用 serviceModel 配置部分是不可能的,因为它会产生安全漏洞。 但是您可以为这些值创建常规 appSettings 并在代码中使用它们:

svc.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings("...")

我建议不要使用这种方法,除非您加密配置文件。

【讨论】:

谢谢。但是将凭据存储在 AppSettings 中仍然需要我以编程方式设置值。我确定这可能是一个安全问题,但我只是看不出区别:人们无论如何都会将登录名/密码存储在某个地方 - 为什么不与 WCF 配置的其余部分一起存储呢? :) 如你所说,与安全有关。为用户提供一种以明文形式指定密码的方法是一个明显的安全漏洞。现在,如果开发人员决定用我提供的代码绕过它,他会意识到自己的错误行为。他将无法说“嘿微软,你的错,你说可以把它放在 WCF 配置中。”

以上是关于在 App.config 中设置 WCF ClientCredentials的主要内容,如果未能解决你的问题,请参考以下文章

C#的app.Config文件中设置,可以选择执行环境(左配置,有程序),app.Config中的appSettings首字母必须小写,符合源码要求

在 WCF 的代码中将 IncludeExceptionDetailInFaults 设置为 true

在 wcf 服务中设置 cookie

在 sharepoint 中设置流式 WCF 服务

在 WCF 服务中设置绑定

在 WCF 项目中设置 Web API