14

WindowsサービスによってホストされているWCFサービスがあります。サービスが実行されているのと同じクレデンシャルを使用してクライアントマシンにログオンすると、クライアントアプリは成功しますが、他の有効なドメインアカウントでログインすると、例外が発生して失敗します。

テストしている2つのアカウントがあります。1つは通常のユーザーアカウントで、もう1つは管理者アカウントです。以下にリストされている4つの組み合わせすべてを試しました。

                   Server account
   CLient      RegUser    AdminAcct   
  RegUser     Succeeds      Fails   
 AdminAcct     Fails       Succeeds    

ご覧のとおり、クライアントとサーバーの両方が非管理者アカウントで実行されている場合はシステムが機能するため、管理者の問題になることはありません。どちらの場合も、サーバーログに何も起きていないという同じ例外がクライアントで発生します。

「SSPIの呼び出しに失敗しました。内部例外を参照してください」

内部の例外は、「ターゲットプリンシパル名が正しくない」です。

アカウントをSPNとして登録しました。

この問題はクライアントアプリからのみ発生しますが、VisualStudioにWCVFTestClient.exe付属しているを使用した場合は発生しません。

WCFトレースログの例外は次のとおりです。

"System.ServiceModel.Security.SecurityNegotiationException、System.ServiceModel、Version = 4.0.0.0、Culture = neutral、PublicKeyToken =b77a5c561934e089"

メッセージ付き:

「リモート側で認証に失敗しました(ストリームは引き続き追加の認証試行に使用できる可能性があります)。」

スタックトレースは一番下にあります:何が問題なのですか?

スタックトレース


System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeAcceptor.OnAcceptUpgrade(Stream stream、SecurityMessageProperty&remoteSecurity)System.ServiceModel.Channels.StreamSecurityUpgradeAcceptorBase.AcceptUpgrade(Stream stream)System.ServiceModel.Channels.InitialServerConnectionReader.UpgradeConnection(IConnection connection、StreamUpgradeAcceptor upgradeAccept System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ServerFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)System.ServiceModel.Dispatcher.ChannelHandler.OpenAndEnsurePump()System.Runtime.ActionItem.DefaultActionItem.TraceAndInvoke() System.Runtime.ActionItem.CallbackHelper。InvokeWithoutContext(Object state)System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode、UInt32 numBytes、NativeOverlapped * nativeOverlapped)System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error、UInt32 bytesRead、NativeOverlapped * nativeOverlapped .PerformIOCompletionCallback(UInt32 errorCode、UInt32 numBytes、NativeOverlapped * pOVERLAP)NativeOverlapped * pOVERLAP)NativeOverlapped * pOVERLAP)

4

2 に答える 2

16

答えが見つかりました。私の問題は2つの要因の組み合わせでした。

  1. net.tcpバイナリWCFプロトコルを使用する場合、クライアントセキュリティモードは、認証にNTLMとKerberosのどちらを使用するかを決定します。クライアントセキュリティモードを「トランスポート」に設定すると、認証はNTLMを使用し、1ホップのみが可能になります。WCFサーバーを(データベースなどの)3番目のサーバーと通信させようとすると、失敗します。SecurityMode = "Message"、otohを使用すると、WCFサーバーはKerberosを使用します。これにより、複数のホップが許可されます...

  2. 2番目の問題は、バインディングでクライアントに対して行っていたことに関連していました。WCFプロトコルnet.tcpでは、クライアントでエンドポイントをインスタンス化するときに、「エンドポイントID」を指定する必要があります(以下のコードを参照)。これは何らかの形で認証に関連していると誤って想定していたため、クライアントに現在ログオンしているユーザー(Windowsプリンシパル)のIDでした。

        var epId = EndpointIdentity.CreateUpnIdentity(userPrincipalName);
        var ep = new EndpointAddress(new Uri(url), epId):
    

    いいえ...クライアントでのエンドポイントの作成で指定する必要があるIDは、サーバーが実行されているIDである必要があります。これが、サービスが実行されているのと同じユーザーでクライアントにログオンするたびにコードが機能し、クライアントが別のユーザーである場合に失敗する理由です。

    この(サービスアカウントの)ユーザーIDをクライアントのエンドポイントで指定する必要がある理由がまだわかりません。このデータはサーバー上のどの機能に必要ですか?

于 2013-03-31T14:51:47.197 に答える
1

2番目の点に関しては、クライアントは正常に認証されるためにサーバーの同じWindowsアカウントで実行する必要はなく、要求でアカウント名を手動で指定する必要もありません。私が理解していることから、WCF認証は相互であり、クライアントがサーバーも検証していることを意味します。

受け取ったエラーは、おそらくクライアント側の障害が原因です。ServicePrincipalNameを提供するようにクライアントのサービスエンドポイントを構成すると、問題が解決する可能性があります。この記事は、私が遭遇した同じ問題を解決するのに非常に役立つことがわかりました。

于 2016-05-19T06:08:32.743 に答える