WCFサービスを呼び出そうとすると、「メッセージのセキュリティを検証中にエラーが発生しました」というメッセージが表示されます。
カスタム認証を削除しても、サービスは問題なく機能します。 web.configで誤って構成したものを理解できません。どんな洞察もいただければ幸いです。
<system.serviceModel>
<services>
<service behaviorConfiguration="NAThriveExtensions.nableAPIBehavior"
name="NAThriveExtensions.nableAPI">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding_Secure"
contract="NAThriveExtensions.InableAPI">
</endpoint>
<endpoint
address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="NAThriveExtensions.nableAPIBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType= "NAThriveExtensions.Authentication, NAThriveExtensions" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding_Secure">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
これは、サービス自体ではなく、消費側の問題になりました。 Software AGのwebMethods 8がこのサーバーを使用していましたが、サービスにセキュリティハンドラーが追加されていないため、資格情報がヘッダーに追加されず、前述のエラーが発生しました。
これと同じエラーメッセージが表示されましたが、ワークステーションマシンとWCFサービスをホストしているサーバーとの時間差が原因であることがわかりました。サーバーは私のマシンから約10分遅れており、WCFセキュリティはそれをあまり気に入らないようです。
根本的な問題を見つけるために、サーバーの構成ファイルでserviceSecurityAuditingをオンにしました。サービスのconfiguration/system.serviceModel/behaviors/serviceBehaviors/behaviorセクションに以下を追加します。
<serviceSecurityAudit
auditLogLocation="Application"
serviceAuthorizationAuditLevel="Failure"
messageAuthenticationAuditLevel="Failure"
suppressAuditFailure="true"/>
次のサイトはこれを理解するのに役立ちました:
このメッセージのもう1つの原因は、一部のマシンが時間的に同期していないことです。 WCFでは、デフォルトで5分のギャップが許可されています。これを超えると、同期がとれていない場合にエラーがスローされます。
解決策は、すべてのマシンを同期することです。 time.windows.com
は機能しないことで悪名が高いため、別の方法を使用することをお勧めします。 (企業環境の場合は、ローカルドメインコントローラーが正しい選択となる場合があります。)
同じエラーが発生しましたが、上記のいずれも役に立ちませんでした。
最後に、それを親web.configのconnectionStringsまで追跡しました(私のサービスは、管理サイトの子アプリケーションにデプロイされました)。
はい、ばかげているように思われますが、接続文字列を親のweb.configでlocation要素でラップするとすぐに、すべてが機能し始めました。
わかりやすくするために、親のweb.configでこれを変更しました
<connectionStrings>
<add name="..." />
</connectionStrings>
これに
<location path="." inheritInChildApplications="false">
<connectionStrings>
<add name="..." />
</connectionStrings>
</location>
このエラーは、この非常に役に立たない serviceSecurityAudit ログメッセージにもなったことに注意してください。
メッセージの認証に失敗しました。
サービス:...
アクション: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT
ClientIdentity:
ActivityId:
ArgumentNullException:値をnullにすることはできません。
パラメーター名:manager
同じエラーが発生しました。メンバーシップデータベースaspnetdbの読み取りアクセス許可を(IIS APPPOOL\DefaultAppPool)に追加するのを忘れました。
メッセージの認証に失敗しました。サービス:....
アクション: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT
ClientIdentity:
ActivityId:
SqlException:ログインで要求されたデータベース "aspnetdb"を開けません。ログインに失敗しました。
ユーザー「IIS APPPOOL\DefaultAppPool」のログインに失敗しました。
同様の問題がありました。 現地時間を使用して日時形式の文字列を構築していましたが、サービス/サーバーは[〜#〜] gmt [〜#〜]を期待していました。
GMT時間を取得する必要がありました(Java):
final Date currentTime = new Date();
final SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.000Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(currentTime));
IIS 7.5サーバーでも同じエラーが発生しました。証明書の秘密キーの読み取りアクセス許可を アプリプールの仮想アカウント に追加するのを忘れました(例:IIS AppPool\ASP.NET v4.0)。
参考までに、アカウントと権限のさまざまな組み合わせをテストしているときに、キーを一度取得すると、キーにアクセスできなくなるため、アプリプールをリサイクルする必要があることに気付きました。
(0x80131501-メッセージのセキュリティを確認中にエラーが発生しました。)