2

我正在做一个利用外部网络服务的网络应用程序。这个外部网络服务要求我签署我的每一个请求。所以我使用WebServicesClientProtocol类和 .NET 2.0,首先使用外部 Web 服务,然后手动编辑Reference.cs文件并将扩展类System.Web.Services.Protocols.SoapHttpClientProtocolMicrosoft.Web.Services2.WebServicesClientProtocol. 然后在Page_Load方法中我有以下代码:

try
{
    // Create the ws endpoint
    var uriServiceAddress = new Uri("urn:something-wse:something_NNNN");
    var uribuilderViaRouter = new UriBuilder("http://xx.xxx.xx/SrvXXX_NNNN/Test.asmx");
    var endpointReference = new EndpointReference(uriServiceAddress, uribuilderViaRouter.Uri);

    // Create the ws client
    var client = (WebServicesClientProtocol) new Test.Something();
    client.Destination = endpointReference;

    // Read the certificate from MyStore on LocalMachine
    X509CertificateStore localStore = X509CertificateStore.LocalMachineStore(X509CertificateStore.MyStore);
    X509SecurityToken securityToken = null;
    if (!localStore.OpenRead()) throw new Exception("Unable to open localstore for read");
    X509CertificateCollection certificateCollection = localStore.FindCertificateBySubjectString("email@subject.test");
    if (certificateCollection.Count == 0) throw new Exception("Unable to obtain security token.");
    securityToken = new X509SecurityToken(certificateCollection[0]);
    localStore.Close();

    // Attach the security toekn to the client request
    client.RequestSoapContext.Security.Tokens.Add(securityToken);
    client.RequestSoapContext.Security.Elements.Add(new MessageSignature(securityToken));

    // Set the timeouts
    client.RequestSoapContext.Security.Timestamp.TtlInSeconds = 2 * 60;
    client.Timeout = 60 * 10 * 1000;    // 10 mínútur ættu að duga í flest.

    // Call the test function
    DataSet set = ((Test.Something)client).searchMethod("Parameter 1", "Parameter 2");
    Label1.Text = User.Identity.Name+ " worked! " + set.Tables.Count + " tables!";
}
catch (Exception exc)
{
    Label1.Text = User.Identity.Name + " exception: " + exc.ToString();
}

当我使用 Visual Studio 开发服务器运行它时,这工作正常,但是当我更改为 IIS 时,它停止工作并且我得到了丑陋的Cryptography_CSP_NoPrivateKey异常。

1)我已经使用 MMC 将证书正确读入 LocalMachine/MyStore,然后我使用 WSE 2.0 SP3 更改了私钥权限,以便每个人都可以完全访问它。你可以从这里看到:

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

2)我还设置了属性,以便在调试应用程序时使用 Visual Studio 开发服务器:

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

3)然后我运行它并得到一个不错的结果:

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

4)但是,当我将属性更改为使用 IIS(并让 VS 创建虚拟目录)时,如下所示:

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

5)我还更改了 IIS 中的身份验证方法,以便我登录(真的没有理由):

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

6)所以我被要求登录Windows:

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

7)然后我的页面运行并产生错误:

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

如果你能帮我解决这个问题,我一定会很感激的。我已经花了几个小时在上面,如果我犯了你们可以看到的基本错误,我不想花更多时间。顺便说一句:我正在 Windows Server 2008 上使用 Visual Studio 2008 进行开发,并关闭了 UAC :-)

真的很期待收到你们的来信。谢谢。

4

1 回答 1

2

:-)

我已经通过几个步骤解决了这个问题:

1)我将用户更改Default Application Pool为我的用户名...

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

......这奏效了。我将应用程序池的用户改回NETWORK SERVICE,但它不再工作。这告诉我问题与NETWORK SERVICE用户有关。所以我回去寻找这个用户的权限可能是什么问题。

2)在浏览和阅读网页时,我在http://timjacobs.blogspot.com/2008/11/app-v-45-certificate-galore.html找到了 Tim Jacobs 的博文App-V 4.5 Certificate Galore。好吧,直到最后他谈到了私钥在磁盘上的存储位置,这里面并没有什么新东西。所以我运行了FindPrivateKey.exe工具,...

C:\MyTools>FindPrivateKey.exe My LocalMachine -t "8c 1a e6 1b 6d f2 f8 18 c8 26 b6 fa cd 60 fd 94 c7 a1 96 58"
私钥目录:
C:\Users\alfred\AppData\Roaming\Microsoft \Crypto\RSA\S-1-5-21-3612370315-2559787 071-3412320394-1135
私钥文件名:
b3765d4123902371ea91c5c9a521932e_96ce3a90-5634-44e6-8aa2-acb123b8b3bf

...这告诉我私钥的位置在C:\Users\alfred\...目录中,NETWORK SERVICE用户可能无权访问此目录!

3)因此,我按照 Tim 的建议使用 MMC 从 导出证书和私钥Local Computer/Personal/Certificates,然后将其导入Local Computer/Trusted Root Certificate Authorities/Certificates. 导出后,FindPrivateKey.exe报告,...

C:\MyTools>FindPrivateKey.exe 我的 LocalMachine -t "8c 1a e6 1b 7d f1 f8 18 c8 26 b6 fa cd 60 fd 94 c7 a1 96 58"
FindPrivateKey 失败,原因如下:没有带有密钥 '8c 1a e6 1b 的证书7d f1 f8 18 c8 26 b6 fa cd 60 fd 94 c7 a1 96 58' 在商店中找到。

...这告诉我出口有效。导入并复制粘贴回来后,Local Computer/Personal/Certificates我得到...

C:\MyTools>FindPrivateKey.exe My LocalMachine -t "8c 1a e6 1b 7d f1 f8 18 c8 26 b6 fa cd 60 fd 94 c7 a1 96 58"
私钥目录:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
私钥文件名:
b3765d4d5a902371ea91c5c9a521932e_96ce3a90-5634-44e6-8aa2-acbaccb8b3bf

...现在私钥在公共场所,即C:\ProgramData\...目录中。然后,我像以前一样使用X509 证书工具NETWORK SERVICE将用户的私钥权限更改为完全访问权限。

现在它起作用了!!!

对于你的博文蒂姆,我实在是太感谢你了。谢谢你。

于 2009-03-25T16:46:13.747 回答