トップ回答者
SecurityNegotiationException が特定のクライアントで発生

質問
-
以前、「同じアドレス、バインディングの場合、ServiceContractAttributeは共有されてしまうのでしょうか? 」にて
質問させていただいたという環境での別の質問です。
別クライアントでデバッグ実行させたところ、以下のエラーが出ます。
System.ServiceModel.Security.SecurityNegotiationException はハンドルされませんでした。
Message="リモート側のセキュリティの必要条件が認証中に満足されませんでした。ProtectionLevel および ImpersonationLevel を増加して実行してください。"
Source="mscorlib"
StackTrace:
Server stack trace:
場所
System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream
stream, SecurityMessageProperty& remoteSecurity)
場所
System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream
stream)
場所
System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator
upgradeInitiator, IConnection& connection, ClientFramingDecoder decoder,
IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper& timeoutHelper)
場所
System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection
connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)
~中略~
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
場所 System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
場所 System.Threading.ThreadHelper.ThreadStart()
InnerException: System.Security.Authentication.AuthenticationException
Message="リモート側のセキュリティの必要条件が認証中に満足されませんでした。ProtectionLevel および ImpersonationLevel を増加して実行してください。"
Source="System"
StackTrace:
場所
System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult
lazyResult)
場所
System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, String targetName, ProtectionLevel requiredProtectionLevel,
TokenImpersonationLevel allowedImpersonationLevel)
場所
System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream
stream, SecurityMessageProperty& remoteSecurity)
InnerException: System.ComponentModel.Win32Exception
Message="ネットワーク ログオンに失敗しました。"
ErrorCode=-2147467259
NativeErrorCode=1790
InnerException:
ネットワークログオンといっても、IISで制限しているわけではないし、ActiveDirectoryでもありません。
これは、 mrt136-2 さんの「特定のクライアントで SecurityNegotiationException が出る 」と、起きている事象自体は似ているのですが、原因は違うような気がします。
ProtectionLevel および ImpersonationLevel というのは、どうやって増加するものなのでしょうか?
すみません、お助けくださいませ。
回答
-
こんにちは
尾画茶さんのセキュリティー用件、ネットワークの環境等がわかっていないので、的を得た回答ができていないかもしれませんが、
それぞれ、このようになるかと。
1. 可能です。認証方法はbindingsセクションで指定します。使用するユーザ情報は、AspMembershipProviderなどのメンバシッププロバイダや、UserNamePasswordValidatorを実装することで、ユーザ名、パスワードを独自で検証することもできます。詳細はMSDNドキュメント等をご参照下さい。
2. よくわかりませんが、単純に認証に失敗しているだけだと思います。netTcpBindingを使用しているようなので、登録に失敗しているわけではないと思います。
3. 登録する必要はありません。クライアントがリッスンするポート情報などの必要な情報はクライアントからサービスに接続するときにサービスに伝えられます。
4. ファイアフォールは確認できる環境がないので答えが正しいか自身がありません。ただ、それ以前に、wshttpbindingの場合、クライアントのリッスンするポートを開く必要があるため、 ポートを開く権限を設定する必要があると思います。なので、そもそもクライアントの設定を変更するという尾画茶さんの要件に違反すると思います。
わたしも、まだまだぜんぜんわかっていないので、はずしているかもしれませんが、参考になれば幸いです。
すべての返信
-
尾画茶 さん こんにちは
以前の環境から続いてとのことですが、どのバインディング(netTcpBinding,basicHttpBinding)でも特定のクライアントでネゴシエーションエラーが発生するということですか?構成を変えていない場合は、netTcpBinding を使用すると、Windows 認証が行われます。basicHttpBinding では認証は行われないはずです。なので、basicHttpBindingを使用すればエラーが発生しないのではと思います。netTcpBindingはWCFクライントを実行しているアカウントとパスワードがWCFサービスが動作しているOS上に存在すれば接続に成功すると思います。
特定のクライアントで SecurityNegotiationException が出る でも、私や他の回答者の方がこたえていますが、セキュリティをなしにしたり、明示的にユーザの資格情報を設定しても同様の現象が起きるのでしょうか?
また、有効な回答できるかわかりませんが、例外が発生するクライアントとそうでないクライアントの違いがあるなら教えて下さい。
偽装、ProtectionLevel に関しては以下のリンクが参考になるかもしれませんが今回はあまり関係ないと思います。
WCF の 委任と偽装
http://msdn.microsoft.com/ja-jp/library/ms730088(VS.85).aspx
方法 : ProtectionLevel プロパティを設定する
http://msdn.microsoft.com/ja-jp/library/aa347791.aspx -
handcraftさん、ご回答ありがとうございます。
今は、そのクライアントを触れない状態なので、再現できません。すみません。
>構成を変えていない場合は、netTcpBinding を使用すると、Windows 認証が行われます。
というのは、知りませんでした。確かに、大丈夫な方は、同じ名前のアカウントが登録してありました。
けれども、Active Directoryではないため、Sidは別ですが、おそらく、ご指摘の点が原因と思われます。
結局、二重通信(Duplex)をしようとすると、バインディングが、限られてくるので、NetTcpBindingを使ったわけですが、すみません、ここで質問させていただきます。
1. NetTcpBindingでWindows認証を行わせない方法はあるのでしょうか?
2. 教えていただいたリンク先は、「サービスがクライアントに偽装」とありますが、Callbackの登録に失敗しているということでしょうか。
3. 別のバインディング策を講じるとして、WsDualHttpBindingは、クライアントのIPを登録する必要があるのでしょうか。
4. また、3の場合、クライアントのファイヤーウォールで引っかかるのではないでしょうか。
環境の条件としては、以下の3点です。
A. Windows認証ができない(しない)
B. クライアントのIPは固定とは限らない
C. クライアントのファイヤーウォール(ただし、クライアント側からの送信は無制限とする)などの設定を変えない
本当に、まだまだ理解できていない、と痛感しております。よろしくお願いいたします。 -
こんにちは
尾画茶さんのセキュリティー用件、ネットワークの環境等がわかっていないので、的を得た回答ができていないかもしれませんが、
それぞれ、このようになるかと。
1. 可能です。認証方法はbindingsセクションで指定します。使用するユーザ情報は、AspMembershipProviderなどのメンバシッププロバイダや、UserNamePasswordValidatorを実装することで、ユーザ名、パスワードを独自で検証することもできます。詳細はMSDNドキュメント等をご参照下さい。
2. よくわかりませんが、単純に認証に失敗しているだけだと思います。netTcpBindingを使用しているようなので、登録に失敗しているわけではないと思います。
3. 登録する必要はありません。クライアントがリッスンするポート情報などの必要な情報はクライアントからサービスに接続するときにサービスに伝えられます。
4. ファイアフォールは確認できる環境がないので答えが正しいか自身がありません。ただ、それ以前に、wshttpbindingの場合、クライアントのリッスンするポートを開く必要があるため、 ポートを開く権限を設定する必要があると思います。なので、そもそもクライアントの設定を変更するという尾画茶さんの要件に違反すると思います。
わたしも、まだまだぜんぜんわかっていないので、はずしているかもしれませんが、参考になれば幸いです。
-
handcraftさん
適切なご回答、ありがとうございます!
bindings セクションのセキュリティーを変更することで、可能でした。
Code Snippet<bindings>
<netTcpBinding>
<binding name="認証なしNetTcpBinding" closeTimeout="00:00:20">
<security mode="None">
<transport clientCredentialType="None" protectionLevel="None" />
<message clientCredentialType="None" />
</security>
</binding>
</netTcpBinding>
</bindings>
↑本当は、None とかはふさわしくないはずですが、とりあえず、ここを変更することで対応できました。
デフォルトで、Windows認証になっていたのは、知りませんでした。
お世話になりました!