通过ssl验证的自定义WCF客户端证书

时间:2012-08-15 09:01:46

标签: wcf validation ssl client-certificates

你好,

我正在尝试使用WCF进行一些身份验证:

  • 使用Username / Passoword
  • 对用户进行身份验证
  • 使用客户端证书验证客户端
  • 自定义接受哪个根证书

经过一些试验和错误,我设法得到积分1& 2工作,但我被困在3.这是我的服务配置

<system.serviceModel>
    <behaviors>
        <endpointBehaviors />
        <serviceBehaviors>
            <behavior name="MyBehavior">
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="Custom"
                                            customUserNamePasswordValidatorType="WcfService1.CustomValidator, WcfService1" />
                </serviceCredentials>                    
                <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <customBinding>
            <binding name="certificate">
                <security authenticationMode="UserNameOverTransport" />
                <textMessageEncoding messageVersion="Soap12WSAddressing10" />
                <httpsTransport requireClientCertificate="true" />
            </binding>
        </customBinding>
    </bindings>
    <services>
        <service behaviorConfiguration="MyBehavior" name="WcfService1.Service1">
            <endpoint address="" binding="customBinding" bindingConfiguration="certificate"
                      contract="WcfService1.IService1" />
        </service>
    </services>
</system.serviceModel>

这是我的客户端配置

    <client>
        <endpoint name="service1" address="https://localhost:443/WcfService1/Service1.svc" binding="customBinding"
                  bindingConfiguration="certificate" behaviorConfiguration="certificate" contract="WcfService1.IService1" />
    </client>
    <behaviors>
        <endpointBehaviors>
            <behavior name="certificate">
                <clientCredentials>
                    <clientCertificate storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"
                                       findValue="SignedByCA" />
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors />
    </behaviors>
    <bindings>
        <customBinding>
            <binding name="certificate">
                <security authenticationMode="UserNameOverTransport" />
                <textMessageEncoding messageVersion="Soap12WSAddressing10" />
                <httpsTransport requireClientCertificate="true" />
            </binding>
        </customBinding>
    </bindings>

使用客户端并附加用户名凭据可以很好地使用

var channelFactory = new ChannelFactory<IService1>("service1");
var user = channelFactory.Credentials.UserName;
user.UserName = username;
user.Password = password;

使用OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets可以访问用户名以及证书的名称和指纹。可悲的是,我无法找到证书的IssuerName。如何禁止没有某个根证书颁发的证书的客户?

任何暗示我指向正确方向或任何替代方案的提示都非常受欢迎;)

由于

1 个答案:

答案 0 :(得分:0)

实际上,这很容易,但是很糟糕。授权上下文中有一个标识列表。

OperationContext.Current.ServiceSecurityContext
.AuthorizationContext.Properties["Identities"]

其中一个是X509Identity类型。那个是System.IdentityModel的内部,你不能直接得到它。

identity.GetType().Name == "X509Identity"

这并不重要,因为包含证书的字段是私有的,无论如何:)

var field = identity.GetType().GetField(
    "certificate", 
    BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
var certificate = (X509Certificate2) field.GetValue(identity);
string issuer = certificate.Issuer;