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

質問
-
いつもお世話になっています。
前回「大きな byte[] の送信に失敗する 」でお世話になった mrt136-2 です。。
今回、またまたハマっています。。
開発環境と、テスト環境の一部では、問題無く接続出来るのですが、
一部のクライアントでは、SecurityNegotiationException が発生してしまいます。
エラーメッセージは以下の通りです。
------ ここからエラーメッセージ ----->
GetData()のエラーです。System.ServiceModel.Security.SecurityNegotiationException: ターゲット'http://testServer/WcfTestService/Service1.svc' のための 'http://testServer/WcfTestService/Service1.svc' との SOAP セキュリティ ネゴシエーションに失敗しました。詳細については、内部例外を参照してください。 ---> System.ComponentModel.Win32Exception: 検証のために提
供されたメッセージまたは署名が変更されています
場所 System.ServiceModel.Security.WindowsSspiNegotiation.Decrypt(Byte[] encryptedContent)
場所 System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver
tokenResolver)(後略)
<---- エラーメッセージここまで ------
また、環境ファイルはサーバ、クライアントでそれぞれ以下の様にしています。
【サーバ】
<system.serviceModel>
<services>
<service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="WcfService1.IService1"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Message"/>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WcfService1.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>【クライアント】
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Message" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://testServer/WcfTestService/Service1.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
<identity>
<servicePrincipalName value="host/testServer" />
</identity>
</endpoint>
</client>
</system.serviceModel>正常に通信出来るクライアントもあるので、クライアント側の問題かとは思うのですが、
エラーを見ても、チェックポイントが分からず困っています。。
何故、署名が変更されているのか。。
これだけの情報で、何かおかしな点、チェックするべき点等がありましたら、ご指導
頂ければ幸いです。。
尚、サーバは、Windows2003Server で IIS6.0にホストしています。
クライアントは、XP,Vistaですが、どちらも正常に通信出来るものと出来ないものがあります。
よろしくお願いいたします。。。
回答
-
こんにちは
Windows認証を使用する場合、アカウントがないなら接続できないほうが正しいと考えているのですが。
というより接続できたほうがセキュリティーてきに問題な気がするので。
(私のWCFのセキュリティに認識に誤りがあるのだろうか?)
ただ、認証に失敗した場合でも最初に掲載されたような署名が変更されている旨のメッセージがでるとは思えないのですが、
何かあるんでしょうかね。
mrt136-2 さんからの引用 ただ、元々成功していたクライアントのユーザもサーバには登録は無かったのですが、
これは、何か原因が考えられますでしょうか。
ひょっとしてNTLM認証のネゴシエーションで、mrt136-2 さんが言われているような(たとえばサーバ上でファイル共有されているファイルにアクセスするときに使用したユーザ名とパスワードを覚えているとか)ことを考えたのですが。接続したことのないマシン上からでも接続できているケースがあるそうなので、なぞですね。
具体的な原因は私には指摘できないのですが、実際にどんなユーザでWCFサービスを呼び出しているのかを確認してみるのがよいのかもしれません。サービス側のオペレーションの実装内で、
System.ServiceModel.OperationContext.Current.ServiceSecurityContext.WindowsIdentityを参照すると、現在アクセスしているユーザの情報がプロパティNameとかいくつか役に立ちそうなプロパティがあるので、調べることができます。
IISで動作させている場合は、ログを出す仕組みを作ったり、もしくはプロセスにアタッチする必要がありますが。
- 回答としてマーク sk7474 2009年2月4日 9:10
すべての返信
-
こんにちは
構成に特に問題はないようにみえます。
同じような事例をみたことがないので、あてずっぽうになってしまい申し訳ないのですが、servicePrincipalNameが設定されていますが、テスト環境は非ドメイン環境ですか?削除しても動くような気がします。(間違ってたらごめんなさい。)
クライアントは動作するものと動作しないものがあると記載されていますが、異なる点はないのでしょうか?
特定のクライアントマシンで必ず失敗するなら原因はクライアントにあるような気がしますが原因はわからないです。
クライアントプログラム内でサーバーに接続するユーザのWindows資格情報を設定して接続したとしても、同様の例外が発生するのですか?
-
handcraft 様
いつもお世話になります。
まず、構成には問題無いと言うことで一つ安心しました。
さて、servicePrincipalName は、削除しても動きました。但し、今まで動いていた環境のみです。
元々SecurityNegotiationException で動いていなかった環境では、同様のエラーで動きません。。
#と言うことは、servicePrincipalName は関係無いと言うことですね。。削除しておきます。
尚、テスト環境としては、テストサーバは非ドメイン環境です。テスト用として、新しいサーバに
Windows2008Server を入れて、その上に Hyper-V で Windows2003Server を載せています。
後、動作するものとしないものの違いについては、特に無い様に見えるのですが、おそらく何かは
あるんでしょうね。。
尚、クライアント側は会社のドメインに入っています。
非ドメイン環境のサーバ(サービス)にドメイン環境にあるクライアントから接続するには何か手順が
必要なのでしょうか。。
#自分の開発環境(ドメイン環境 XP Pro sp3)からテストサーバへの接続は問題無く行えています。
> クライアントプログラム内でサーバーに接続するユーザのWindows資格情報を設定して接続したとしても、
> 同様の例外が発生するのですか?
あまりの無知さにお恥ずかしい限りですが、これは具体的にはどの様にするのでしょうか?
ご教示頂ければ幸いです。
#私自身でもこれから調べてみます。。
-
こんにちは
結構最新な環境なのですね。
mrt136-2 さんからの引用 さて、servicePrincipalName は、削除しても動きました。但し、今まで動いていた環境のみです。
元々SecurityNegotiationException で動いていなかった環境では、同様のエラーで動きません。。
#と言うことは、servicePrincipalName は関係無いと言うことですね。。削除しておきます。
あっても特に問題はないと思うのですが、servicePrincipalNameを見た限り、サーバはドメインに参加していないようだったので、設定しても使われないかなとおもった程度ですので、あまり気にする必要はないと思います。
mrt136-2 さんからの引用 > クライアントプログラム内でサーバーに接続するユーザのWindows資格情報を設定して接続したとしても、
> 同様の例外が発生するのですか?
あまりの無知さにお恥ずかしい限りですが、これは具体的にはどの様にするのでしょうか?
ご教示頂ければ幸いです。
#私自身でもこれから調べてみます。。
の件ですが、クライアントはプロキシクラスのインスタンスを作成してからサービスのオペレーションを呼び出していると思います。
なので、プロキシインスタンスを作成した直後に、次のようにWindowsの資格情報を設定します。proxyがプロキシクラスのインスタンスと仮定します。
proxy.ClientCredentials.Windows.ClientCredential.Domain = @"";
proxy.ClientCredentials.Windows.ClientCredential.UserName = @"testServer\WCFTestUser";
proxy.ClientCredentials.Windows.ClientCredential.Password = @"WCFtest001";UserName,Passwordはサーバにアクセスできるユーザの情報を設定してください。
こうすると、ログインしているユーザではなく、プログラム内で指定したユーザの資格情報を使って接続できるはずです。
って書いていて思ったのですが、クライアントはドメインに所属していて、サーバはドメインに所属していないとありますが、ドメインユーザと同じアカウントとパスワードを持つユーザがサーバに用意されているのですか?
-
handcraft 様
いつも迅速なご回答に頭が下がります。。
> 結構最新な環境なのですね。
無知なくせに、最新のものを試したくなる好奇心だけ旺盛なのです。。。
#最新のものの方がきっと良いはず!と言う根拠のない考えからですが。。
Windowsの資格情報の件、ありがとうございました。
#ちょっと今回も恥ずかしい内容になる予感がプンプンしています。。。
サーバにはドメインユーザと同様のユーザ情報はありませんです。。
で、ご指摘の通り、クライアントのコードで資格情報を設定する事で正常に
通信出来ることを確認しました。
ただ、元々成功していたクライアントのユーザもサーバには登録は無かったのですが、
これは、何か原因が考えられますでしょうか。
一度、このサーバに接続した事のあるユーザだったから繋がったのでしょうか?
#いや、全く関係の無いVistaマシンからでも接続出来ていました。
とにかく、Windowsの資格情報の問題であろうと言うことは理解出来ましたので、
一歩、二歩先には進めそうですが、繋がっていたのが何故か?が分からないと
ちょっと気持ち悪いですね。。
何か考えられるような内容はありますでしょうか。。
-
こんにちは
Windows認証を使用する場合、アカウントがないなら接続できないほうが正しいと考えているのですが。
というより接続できたほうがセキュリティーてきに問題な気がするので。
(私のWCFのセキュリティに認識に誤りがあるのだろうか?)
ただ、認証に失敗した場合でも最初に掲載されたような署名が変更されている旨のメッセージがでるとは思えないのですが、
何かあるんでしょうかね。
mrt136-2 さんからの引用 ただ、元々成功していたクライアントのユーザもサーバには登録は無かったのですが、
これは、何か原因が考えられますでしょうか。
ひょっとしてNTLM認証のネゴシエーションで、mrt136-2 さんが言われているような(たとえばサーバ上でファイル共有されているファイルにアクセスするときに使用したユーザ名とパスワードを覚えているとか)ことを考えたのですが。接続したことのないマシン上からでも接続できているケースがあるそうなので、なぞですね。
具体的な原因は私には指摘できないのですが、実際にどんなユーザでWCFサービスを呼び出しているのかを確認してみるのがよいのかもしれません。サービス側のオペレーションの実装内で、
System.ServiceModel.OperationContext.Current.ServiceSecurityContext.WindowsIdentityを参照すると、現在アクセスしているユーザの情報がプロパティNameとかいくつか役に立ちそうなプロパティがあるので、調べることができます。
IISで動作させている場合は、ログを出す仕組みを作ったり、もしくはプロセスにアタッチする必要がありますが。
- 回答としてマーク sk7474 2009年2月4日 9:10
-
handcraft 様
> Windows認証を使用する場合、アカウントがないなら接続できないほうが正しいと考えているのですが。
> というより接続できたほうがセキュリティーてきに問題な気がするので。
> (私のWCFのセキュリティに認識に誤りがあるのだろうか?)
おっしゃる通りだと思います。
ただ、
> ただ、認証に失敗した場合でも最初に掲載されたような署名が変更されている旨のメッセージがでるとは思えないのですが、
> 何かあるんでしょうかね。
と、
> ひょっとしてNTLM認証のネゴシエーションで、mrt136-2 さんが言われているような(たとえばサーバ上でファイル共有されている> ファイルにアクセスするときに使用したユーザ名とパスワードを覚えているとか)ことを考えたのですが。接続したことのないマシン> 上からでも接続できているケースがあるそうなので、なぞですね。
があるので、「何故繋がるマシンがあったの??」となってしまうのです。。
> System.ServiceModel.OperationContext.Current.ServiceSecurityContext.WindowsIdentityを参照すると、現在アクセスして> いるユーザの情報がプロパティNameとかいくつか役に立ちそうなプロパティがあるので、調べることができます。
こちらについては、一度確認してみます。
ありがとうございました。また、何か解れば書き込みます。
-
まどか 様
ご回答ありがとうございます。
クライアントは現在ClickOnceで配布している状態で、確認しましたが、同じものでした。
また、Security Mode="None" では正常に接続出来ます。
OSに関しては、XP,Vista共、接続出来るものと出来ないものがそれぞれあるので、
お手上げ気味だった次第です。。。
ただ、私がWindows認証でユーザが無かったのは完全に間抜けな事をしていたので、
それはNGなんですけどね。。
今度は、何故繋がっていたクライアントがあったのか。。と言うことが謎なんです。。
もうちょっと調べてみます。
ご回答ありがとうございました。