1

我将 WebServicesClientProtocol 类与安全令牌一起使用,并使用以下代码查找要使用的安全令牌:

private static X509SecurityToken GetSecurityCertificate(string subject)
{
    X509CertificateStore localStore = X509CertificateStore.LocalMachineStore(X509CertificateStore.MyStore);
    X509SecurityToken securityToken = null;
    if (localStore.OpenRead())
    {
       X509CertificateCollection certificateCollection = localStore.FindCertificateBySubjectString(subject);
        if (certificateCollection.Count == 0) throw new Exception("Skilríki finnst ekki í skilríkjageymslu");
        securityToken = new X509SecurityToken((X509Certificate)certificateCollection[0]);
    }
    localStore.Close();
    return securityToken;
}

时不时地(但并非总是如此,而且我无法确定确切的时间)我得到以下异常:

替代文字 http://www1.ruedenet.is/files/exception.png

4

1 回答 1

1

我今天遇到了这个问题,我相信我已经弄清楚是什么原因造成的。静态方法需要同步。

如果您在异常发生时将鼠标悬停在 localStore 变量上并检查 Certificates 属性,您很可能会看到“InvalidOperationException - 要访问您必须使用 Open() 或 OpenRead() 的证书......等等。呜呜呜”。

正在发生的事情是某个线程在另一个线程完成访问它之前关闭了存储。

我通过首先创建一个静态类成员来锁定存储解决了这个问题:

private static object m_storeLock = new object();

当您访问商店时,您必须执行以下操作:

public static X509Certificate FindCertificate(string certName) {
    X509CertificateStore store = null;            
    X509Certificate cert = null;

    lock (m_storeLock) {
        try {                    
            store = X509CertificateStore.LocalMachineStore(X509CertificateStore.MyStore);
            store.OpenRead();

            X509CertificateCollection col =
            (X509CertificateCollection)store.FindCertificateBySubjectString(certName);

            if (col.Count > 0) {      
                cert = col[0];
            }
        }
        catch {
        }
        finally {
            if (store != null) {
                store.Close();
            }
        }
    }                           

    if (cert == null) {
        throw new ArgumentException("Certificate not found!");
    }

    return cert;
}

为了更加安全,您可能应该锁定局部变量“cert”,但这不是生产代码的家伙......:D~

于 2009-08-18T21:33:43.340 回答