17

偽装とセッションが必要な WCF サービスを作成しています。

ローカルマシンで呼び出そうとしたときは問題ありませんが、リモートマシンでは常に次のエラーで失敗しました:

Security Support Provider Interface (SSPI) 認証に失敗しました。サーバーが ID 'host/hostname' のアカウントで実行されていない可能性があります。サーバーがサービス アカウント (ネットワーク サービスなど) で実行されている場合は、アカウントの ServicePrincipalName をサーバーの EndpointAddress の ID として指定します。サーバーがユーザー アカウントで実行されている場合は、アカウントの UserPrincipalName をサーバーの EndpointAddress の ID として指定します。

upn を指定すると、ID 失敗の例外がスローされます。

これが私の設定です:

サーバー構成 (アプリ):

<system.serviceModel>    
    <behaviors>
      <serviceBehaviors>
        <behavior name="default">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="DataService.netTcpBinding">
          <readerQuotas maxArrayLength="65535" maxBytesPerRead="2147483647" maxStringContentLength="2147483647"/>
          <reliableSession enabled="true" inactivityTimeout="24:00:00" ordered="true"/>          
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="Windows" />
            <transport clientCredentialType="Windows"/>          
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
    <services>
      <service behaviorConfiguration="default" name="DataService.DataService">
        <endpoint address="" binding="netTcpBinding" bindingConfiguration="DataService.netTcpBinding" 
          name="DataService.DataService" contract="DataService.IDataService"/>
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://address:4504/"/>
            <add baseAddress="net.tcp://address:4503/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
</system.serviceModel>

クライアント構成:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>     
        <bindings>
            <netTcpBinding>
                <binding name="DataService.DataService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                    hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                    maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
                    maxReceivedMessageSize="65536">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="24.00:00:00"
                        enabled="true" />
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                        <message clientCredentialType="Windows" algorithmSuite="Default" />
                    </security>
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://address:4503/" binding="netTcpBinding"
                bindingConfiguration="DataService.DataService"
                contract="ataService.IDataService" name="DataService.DataService">
              <identity>
                <dns value="DOMAIN"/>                                                  
              </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

どんな助けでも大歓迎です。

4

2 に答える 2

23

Windows サービスは、ユーザー プリンシパル名またはサービス プリンシパル名のいずれかを使用して自身を登録します (ドキュメント)。そのリンクからの引用: 「サービスが LocalSystem、LocalService、または NetworkService アカウントで実行されている場合、これらのアカウントはコンピューターの SPN データにアクセスできるため、サービス プリンシパル名 (SPN) はデフォルトで host/ の形式で生成されます。サービスが別のアカウントで実行されている場合、Windows Communication Foundation (WCF) は @ の形式で UPN を生成します。実際、この引用は、エラー メッセージが示している内容とかなり似ています。それで、どうやら...

a) サービスがローカル サービス アカウントまたは同様の標準アカウントで実行されている場合、クライアント構成ファイルを調整して、これを保持する必要があります。実際のサーバーの名前は「アドレス」であり、エンドポイントはポート 4503 で実行されています。

<identity>
     <servicePrincipalName value="host/address:4503" />
</identity>

b) あるいは、専用のサービス アカウント (ドメイン "MyDomain" の "ServiceAccount" と呼びましょう) で実行している場合は、

<identity>
     <userPrincipalName value="ServiceAccount@MyDomain" />
</identity>

フォレスト レベルとツリー レベルを含め、両方の場合で完全修飾ドメイン名を使用する必要がある場合があることに注意してください。プライベート LAN/WAN 内の単純なドメインの場合、address.MyDomain.local と ServiceAccount@MyDomain.local を意味します。ドメインが MyTree というツリーにある場合は、ServiceAccount@MyDomain.MyTree.local になります。それが MyForest という名前のフォレストにある場合は、Serviceaccount@MyDomain.MyTree.MyForest.local (ServicePrincipalName も同様) になります。認証にKerberos を使用している場合は、完全修飾名が必要です。

于 2013-05-31T02:12:17.423 に答える
8

ここここ、およびここに投稿され、ここで分析されているように、汚いハックもあります。

ダミーのサービス プリンシパル名 (SPN) を指定できます。その場合、WCF は失敗しませんが、プリンシパルを検証しない認証のために NTLM にフォールバックします。

したがって、構成:

    <identity>
      <servicePrincipalName value="dummy" >
    </identity>

そしてプログラム的に

    EndpointIdentity identity = EndpointIdentity.CreateSpnIdentity("dummy");

ChannelFactory を使用:

    Uri uri = new Uri("net.tcp://<myServer>:<myPort>/myServiceAddress");
    ChannelFactory channelFactory = new ChannelFactory<IMyContract>(new NetTcpBinding());
    channelFactory.CreateChannel(new EndpointAddress(uri, identity)

も機能します。

于 2013-11-08T01:01:49.810 に答える