安全なWebサービスを作成しようとしています。
これが契約とサービスの実装です
[ServiceContract()]
public interface ICalculatorService
{
[OperationContract()]
int Add(int x, int y);
}
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class CalculatorService : ICalculatorService
{
public int Add(int x, int y)
{
return x + y;
}
}
ここにサービスコードがあります
var b = new WSHttpBinding(SecurityMode.Transport);
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
Type contractType = typeof(ICalculatorService);
Type implementedContract = typeof(CalculatorService);
Uri baseAddress = new Uri("https://localhost:8006/CalculatorService");
ServiceHost sh = new ServiceHost(implementedContract);
sh.AddServiceEndpoint(contractType, b, baseAddress);
//ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
//sm.HttpsGetEnabled = true;
//sm.HttpsGetUrl = new Uri("https://localhost:8006/CalculatorServiceMex");
//sh.Description.Behaviors.Add(sm);
sh.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
sh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
sh.Open();
Console.WriteLine("Service is Listening");
Console.ReadLine();
sh.Close();
ここにクライアントコードがあります
var b = new WSHttpBinding(SecurityMode.Transport);
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
var factory = new ChannelFactory<ICalculatorService>(b);
factory.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
var client = factory.CreateChannel(new EndpointAddress(new Uri("https://localhost:8006/CalculatorService")));
ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) =>
{
return true;
});
ICommunicationObject comObject = client as ICommunicationObject;
int result = -1;
try
{
comObject.Open();
result = client.Add(10, 2);
}
catch (Exception ex)
{
}
Console.WriteLine(string.Format("Service say 10 + 2 = {0}", -1));
Console.ReadLine();
サービスは正常に実行され、ServicePointManager.ServerCertificateValidationCallbackチェックが行われると、ポリシーエラーは発生せず、正しい証明書チェーンが構築されます。
信頼されたルートにCAがあり、TrustedPeopleストアにサーバー/クライアント証明書があります。また、ブラウザからサイトに移動すると、ページが返されます。エラーなし
IISが必要だと思うものに更新し、IIS
そして、以下のコマンドラインから。
証明書を受け入れるようにSSL設定を設定しました
匿名認証を有効にしました。
誰かが私が正しく行っていないステップを知っていますか、何かおかしいと思いますか?同じエラーが発生し続けます"HTTP要求はクライアント認証スキーム '匿名'で禁止されていました。"
これの別の理由は、ヒットしているサーバー上の証明書自体です。プライベートキーをインポートしたことを確認してください。 In MMCこれは「フレンドリ名」で表示されます。これを理解するには数日かかりました。秘密鍵をインポートすると、匿名エラーはなくなり、すべて順調です。
WCFサービスをIISセキュリティタイプトランスポートおよびクライアントクレデンシャルタイプ証明書でホストする場合、ルートストアにクライアント証明書を置き、IISで匿名認証を有効にします。 IISで匿名認証を有効にします。しかし、最も重要なのは、ルートストアに証明書を追加することです。
自己ホスト型のWCFサービス(IISなし)を実行する場合、confingファイル(サーバー内)に以下を追加することにより、匿名クライアントを有効にできます。
<behaviors>
<serviceBehaviors>
<behavior name="limitedAuthBehavior">
<serviceAuthenticationManager authenticationSchemes="Anonymous, Basic, Digest, Negotiate"/>
<!-- ... -->
</behavior>
</serviceBehaviors>
</behaviors>
また、clientCredentialTypeを「InheritedFromHost」に設定します。
<bindings>
<basicHttpBinding>
<binding name="secureBinding">
<security mode="Transport">
<transport clientCredentialType="InheritedFromHost" />
</security>
</binding>
</basicHttpBinding>
</bindings>
参照:
このエラーメッセージがありましたが、解決策は、スクリプトに対してハンドラーマッピング機能のアクセス許可が有効になっていないことでした。これを有効にするには、IIS [ハンドラーマッピング]> [機能のアクセス許可の編集]で、またはScript
ノードのaccessPolicy
属性にhandlers
を追加します。 web.configで:
<system.webServer>
<handlers accessPolicy="Script">
...
</handlers>
</system.webServer>