13,009
回編集
(→受信) |
|||
| 355行目: | 355行目: | ||
以下の例では、SSL / TLS証明書を使用して、非同期でサーバに接続およびメッセージを受信している。<br> | 以下の例では、SSL / TLS証明書を使用して、非同期でサーバに接続およびメッセージを受信している。<br> | ||
また、タイムアウトが発生した場合の再試行処理や高度なエラー処理等も追加することを推奨する。<br> | また、タイムアウトが発生した場合の再試行処理や高度なエラー処理等も追加することを推奨する。<br> | ||
<br> | |||
<u>※注意</u><br> | |||
<u>サーバ側でもSSL / TLS証明書の対応が必要となる。</u><br> | |||
<u>実務では、適切な証明書の管理と定期的な更新が重要である。</u><br> | |||
<br> | <br> | ||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
| 422行目: | 426行目: | ||
Console.WriteLine($"予期せぬエラーが発生: {e.Message}"); | Console.WriteLine($"予期せぬエラーが発生: {e.Message}"); | ||
} | } | ||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// ※注意 | |||
// 実務では、使用環境に応じて、さらに厳密な検証ロジックを追加することを推奨する。 | |||
// また、可能な限り信頼された認証局によって発行された証明書を使用することを推奨する。 | |||
// | |||
// 信頼された証明書のリストは定期的に更新して、不要になった証明書は速やかに削除すること。 | |||
using System; | |||
using System.Net.Security; | |||
using System.Security.Cryptography.X509Certificates; | |||
public class SslCertificateValidator | |||
{ | |||
// 信頼された証明書のサムプリント | |||
// 実際の環境に合わせて更新すること | |||
private static readonly string[] TrustedCertificates = new string[] | |||
{ | |||
"A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0", | |||
"B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1" | |||
}; | |||
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) | |||
{ | |||
if (sslPolicyErrors == SslPolicyErrors.None) | |||
{ // 証明書チェーンとポリシーエラーが無い場合 | |||
LogMessage("情報", "証明書の検証に成功"); | |||
return true; | |||
} | |||
LogMessage("警告", $"証明書エラー: {sslPolicyErrors}"); | |||
if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)) | |||
{ | |||
return HandleChainErrors(chain); | |||
} | |||
if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) | |||
{ | |||
LogMessage("エラー", "証明書の名前が不一致"); | |||
return false; | |||
} | |||
if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable)) | |||
{ | |||
LogMessage("エラー", "リモート証明書が利用不可"); | |||
return false; | |||
} | |||
// その他のエラーの場合 | |||
return false; | |||
} | |||
private static bool HandleChainErrors(X509Chain chain) | |||
{ | |||
foreach (X509ChainStatus status in chain.ChainStatus) | |||
{ | |||
if (status.Status == X509ChainStatusFlags.UntrustedRoot) | |||
{ | |||
X509Certificate2 rootCert = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; | |||
if (ValidateSelfSignedCertificate(rootCert)) | |||
{ | |||
LogMessage("情報", "信頼されたルート証明書を確認"); | |||
return true; | |||
} | |||
} | |||
LogMessage("エラー", $"証明書チェーンエラー: {status.StatusInformation}"); | |||
} | |||
return false; | |||
} | |||
private static bool ValidateSelfSignedCertificate(X509Certificate certificate) | |||
{ | |||
string certHash = certificate.GetCertHashString(); | |||
if (TrustedCertificates.Contains(certHash, StringComparer.OrdinalIgnoreCase)) | |||
{ | |||
LogMessage("情報", "信頼された自己署名証明書を確認"); | |||
return true; | |||
} | |||
LogMessage("エラー", $"未知の自己署名証明書を確認 サムプリント: {certHash}"); | |||
return false; | |||
} | |||
private static void LogMessage(string level, string message) | |||
{ | |||
string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{level}] {message}"; | |||
Console.WriteLine(logMessage); | |||
// ファイルやデータベースへのログ記録処理等を追加 | |||
} | } | ||
} | } | ||