使用 MySQL TLS 的经典 ASP 中的 CryptographicException

CryptographicException in Classic ASP with MySQL TLS

当我尝试调用 classic ASP 页面中的 COM Visible c# class 时,我遇到了这个问题,该页面试图执行一个 MySQL 查询数据库。(此处 MySQL 在 TLS 上)。

在我的案例中,classic asp 页面之一,我们创建了 SomeUser class 的实例,然后调用 SetId 方法来尝试创建 MySQL 连接并失败并显示此堆栈跟踪 。为了完全清楚起见,这里 SomeUser class 是 COMVisible。

经典ASP代码段

dim dummy: set dummy= new SomeUser
dim dummyObj: set dummyObj= dummy.obj

dummyObj.SetId(ID)

异常

System.Security.Cryptography.CryptographicException: The system cannot find the file specified. 
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) 
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx) at System.Security.Cryptography.X509Certificates.X509Utils.LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle pCertCtx) 
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags) 
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password) at MySql.Data.MySqlClient.NativeDriver.GetClientCertificates() 
at MySql.Data.MySqlClient.NativeDriver.StartSSL() at MySql.Data.MySqlClient.NativeDriver.Open() at MySql.Data.MySqlClient.Driver.Open() 
at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings) at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection() 
at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection() at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver() at MySql.Data.MySqlClient.MySqlPool.GetConnection() 
at MySql.Data.MySqlClient.MySqlConnection.Open() at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) 
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior) 
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable) at Some.Other.Namespace.Execute(MySqlConnection connection, String sql, DataTable table, DataParameter[] dataParameters) at Some.Other.Namespace.Execute(MySqlConnection connection, String sql, DataParameter[] dataParameters) at Some.Other.Namespace.Execute(String sql, DataParameter[] dataParameters) 
at SomeNamespace.SomeDc.GetData(UInt32 Id) at 
SomeNamespace.User.GetData(UInt32 ID) at SomeNameSpace.SomeUser.SetId(Int32 Id)

Similar question on Stack Overflow 就此.

在我的例子中,此解决方案(将加载用户配置文件设置为 true)仅适用于 ASPX 页,但在本例中无效。

还有一点我想强调 w3wp.exe 是 运行 in Default App Pool with ApplicationPoolIdentity.

到目前为止我已经尝试了很多东西但没有成功。方向正确的任何一点都会有很大帮助。

到目前为止我已经尝试过的事情。

我对ASP一无所知,所以我不明白你试过什么。

但是,异常日志似乎告诉了哪里出了问题。 ASP / COM 应用程序在连接到 MySQL 服务器时试图加载 客户端 证书,但找不到相应的文件。这可能是由于权限问题,也可能只是因为该文件不存在。

请注意,这是一个 not-so-common 问题,可能会妨碍您快速找到解决方案。证书问题通常是由于 服务器 证书不受信任、吊销或过时。但在这种情况下,COM 部分试图加载 client 证书,以便它可以证明 its 身份 to服务器。

解决问题的方法视情况而定:

  • 如果您控制着 MySQL 服务器,您可以将其配置为不请求客户端证书。然后 COM 代码不再需要加载客户端证书,您可以相应地更改 COM 对象的行为。但是,在服务器上关闭客户端身份验证可能不安全。

  • 您似乎控制了 COM 代码,因此您可以重新访问它并查看它尝试加载 MySQL 客户端证书的位置。检查它试图加载哪个文件,并检查文件系统上是否有该文件。如果不存在,并且无法在没有客户端证书的情况下工作,则您必须生成客户端证书。
    不过,我不知道 COM 对象是如何工作的。即使您没有找到它试图显式加载客户端证书的地方,它也可能会评估一些 MySQL 客户端配置文件,告诉它在连接到服务器时使用(特定)客户端证书。此类文件的名称可能类似于 mysql.inimy.inimy.cnf 等。

澄清:以上段落是关于 MySQL TLS 连接的 MySQL 客户端 证书。这与网络服务器证书无关。

如果需要MySQL客户端认证,请一步步测试:

  1. 生成适当的 MySQL 客户端证书。
  2. 将该客户端证书与私钥一起放到运行 COM 应用程序的计算机上。
  3. 登录那台机器并在那里安装本机MySQL客户端(它可用于Windows)。
  4. 在那台机器上,尝试使用客户端身份验证与您的 MySQL 服务器建立加密连接,使用本机 MySQL 客户端 并使用您的客户端证书.
    如果这不起作用,它可能无法在您的 COM 对象中起作用,因此您需要先解决这个问题。
  5. 在最后一步中,再次尝试 ASP 应用程序/COM 对象。确保它有足够的权限读取证书和私钥,并且两者都存在于预期的位置。

如果与本机客户端连接成功,但 COM 对象仍然无法连接,我可能对如何调试这种情况有了额外的想法。在那种情况下,只需发表评论即可;我最终会修改这个答案。