我有一个非常奇怪的问题。我发布了一个webrole到azure云服务。在这个项目中,它需要webrole调用Azure Rest API,我可以在本地模拟器中获取响应,但是,如果我将其发布到Azure,我会得到403禁止错误。我确信我已将证书安装到Azure。
可以通过以下步骤重现此错误:
控制台应用代码:
static void Main(string[] args)
{
try
{
// X.509 certificate variables.
X509Store certStore = null;
X509Certificate2Collection certCollection = null;
X509Certificate2 certificate = null;
// Request and response variables.
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
// Stream variables.
Stream responseStream = null;
StreamReader reader = null;
// URI variable.
Uri requestUri = null;
// Specify operation to use for the service management call.
// This sample will use the operation for listing the hosted services.
string operation = "hostedservices";
// The ID for the Windows Azure subscription.
string subscriptionId = "";
// The thumbprint for the certificate. This certificate would have been
// previously added as a management certificate within the Windows Azure management portal.
string thumbPrint = "";
// Open the certificate store for the current user.
certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
// Find the certificate with the specified thumbprint.
certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
thumbPrint,
false);
// Close the certificate store.
certStore.Close();
// Check to see if a matching certificate was found.
if (0 == certCollection.Count)
{
throw new Exception("No certificate found containing thumbprint " + thumbPrint);
}
// A matching certificate was found.
certificate = certCollection[0];
Console.WriteLine("Using certificate with thumbprint: " + thumbPrint);
// Create the request.
requestUri = new Uri("https://management.core.windows.net/"
+ subscriptionId
+ "/services/"
+ operation);
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(requestUri);
// Add the certificate to the request.
httpWebRequest.ClientCertificates.Add(certificate);
// Specify the version information in the header.
httpWebRequest.Headers.Add("x-ms-version", "2011-10-01");
// Make the call using the web request.
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
// Display the web response status code.
Console.WriteLine("Response status code: " + httpWebResponse.StatusCode);
// Display the request ID returned by Windows Azure.
if (null != httpWebResponse.Headers)
{
Console.WriteLine("x-ms-request-id: "
+ httpWebResponse.Headers["x-ms-request-id"]);
}
// Parse the web response.
responseStream = httpWebResponse.GetResponseStream();
reader = new StreamReader(responseStream);
// Display the raw response.
Console.WriteLine("Response output:");
Console.WriteLine(reader.ReadToEnd());
// Close the resources no longer needed.
httpWebResponse.Close();
responseStream.Close();
reader.Close();
}
catch (Exception e)
{
Console.WriteLine("Error encountered: " + e.Message);
// Exit the application with exit code 1.
Console.ReadLine();
System.Environment.Exit(1);
}
finally
{
// Exit the application.
Console.ReadLine();
System.Environment.Exit(0);
}
}
答案 0 :(得分:7)
我使用您提供的azure create cert链接遇到了同样的问题。我发现在使用该方法创建证书时,私钥未被上传到云服务。即使该服务能够找到证书,但在提交请求时仍然是未经授权的。
使用以下方法创建私钥和公钥证书。在Visual Studio命令提示符中,创建.cer
和.pfx
文件:
makecert -r -pe -n "CN=AzureManage" -sky exchange "AzureManage.cer" -sv "AzureManage.pvk"
pvk2pfx -pvk "AzureManage.pvk" -spc "AzureManage.cer" -pfx "AzureManage.pfx" -pi password
第一个命令创建私钥和公钥文件。系统将提示您输入密码几次。第二个命令将两者合并为一个pfx文件。如果您关闭-pi password
,系统将提示您输入密码,而不是在终端中输入密码。
然后,您需要适当地导入文件:
然后,您可以按如下方式使用Azure管理REST API:
X509Certificate2 GetCertificate(string thumbprint)
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (certs.Count == 0) return null;
var cert = certs[0];
store.Close();
return cert;
}
HttpWebRequest request = WebRequest.CreateHttp(apiUrl);
request.ClientCertificates.Add(cert);
request.Headers.Add("x-ms-version", "2012-03-01");
答案 1 :(得分:1)
我相信你的问题在于这行代码:
certStore = new X509Store(StoreName.My, **StoreLocation.CurrentUser**);
我希望正确上传的证书(假设它是通过管理门户正确上传的.pfx)存储在LocalMachine商店中,而不是CurrentUser。
此外,为了从证书存储中读取证书,您的角色需要以完全信任的方式运行(可以在Visual Studio的角色项目属性中指定/验证)
答案 2 :(得分:0)
+1 @Igorek。我遇到了类似的问题。如果我在我的配置中指定证书应该安装在CurrentUser
商店中,我发现对于Web角色,certifcate会安装在那里,但对于Worker角色,证书安装在LocalUser
商店中。
然而,看起来这不是问题的根本原因。您是否可以确保门户网站Management Certificates
部分下面有相同的证书(以cer文件格式将其导出并在那里上传),并且角色中安装的证书附加了私有属性。这两个原因是403错误的主要原因。