0

こんにちは、

私はいくつかの認証を行うためにWCFを使用しようとしています:

  • ユーザー名/パスワードを使用してユーザーを認証する
  • クライアント証明書を使用してクライアントを認証する
  • 受け入れるルート証明書をカスタマイズする

いくつかの試行錯誤の後、ポイント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 が見つかりません。特定のルート証明書によって発行された証明書を持たないクライアントを禁止するには、他にどのような方法がありますか?

私を正しい方向に向けるヒントや代替手段は大歓迎です;)

ありがとう

4

1 に答える 1

0

実際、それは簡単ですが、ハックです。認証コンテキストには ID のリストがあります。

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

そのうちの 1 つは 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;
于 2012-08-15T14:59:34.217 に答える