系统在 Azure 服务器中找不到使用 X509Certificate2 连接 Google OAuth2.0 指定的文件
The system cannot find the file specified using X509Certificate2 to connect Google OAuth2.0 in an Azure Server
我正在使用此代码连接到 Google OAuth2.0,并且我正在使用 C# 库。
using (var tImpersonationContext = new ImpersonationContext(ConfigurationManager.AppSettings["ImpersonationDomain"], ConfigurationManager.AppSettings["ImpersonationUser"], ConfigurationManager.AppSettings["ImpersonationPassword"]))
{
string[] tScopes = new string[] { AnalyticsService.Scope.Analytics };
var tKeyFilePath = Path.Combine(System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]), String.Format("GoogleCertificates\{0}", this.OAuthKeyName));
var tServiceAccountEmail = this.OAuthServiceAccountEmail;
//loading the Key file
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable);
var tCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(tServiceAccountEmail)
{
Scopes = tScopes
}.FromCertificate(tCertificate));
if (tCredential.RequestAccessTokenAsync(CancellationToken.None).Result)
{
this.SessionToken = tCredential.Token.AccessToken;
}
}
在我的开发环境中,一切都运行得非常完美,但是当我将应用程序移至我的 Azurre 服务器时,出现了这个错误:
The system cannot find the file specified.
当我尝试执行这一行时:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable);
我确定路径是正确的,事实上,如果我在文件资源管理器中复制并粘贴路径,导入证书的向导就会启动。
我确定模拟有效,因为该行已被执行。
我试过改成:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.MachineKeySet);
或者这样:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.UserProtected | X509KeyStorageFlags.DefaultKeySet);
而且没有任何效果,事实上,我从该网站的其他问题中尝试的所有内容都没有效果。
如果有帮助,我假装在计划任务中使用的 Windows 应用程序可以从 Google 分析中获取数据。
有人知道为什么不能在 Azure 服务器上工作吗?
提前致谢。
更新:
我已尝试安装证书并将代码更改为:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.MachineKeySet);
但是现在我有这个错误:
Key not valid for use in specified state.
我已经更改了方法中的所有代码,现在可以正常工作了。
首先,您必须在证书下受信任的根证书颁发机构内的 MMC 管理器中安装证书,并且必须将其设置为本地计算机。
然后你只需要使用这个代码:
X509Store tCertStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
tCertStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection tCertCollection = tCertStore.Certificates.Find(X509FindType.FindByThumbprint, this.OAuthKeyFingerprint, false);
// Get the first cert with the thumbprint
if (tCertCollection.Count > 0)
{
// header
var tHeader = new { typ = "JWT", alg = "RS256" };
// claimset
var tTimes = GetExpiryAndIssueDate();
var tClaimset = new
{
iss = this.OAuthServiceAccountEmail,
scope = "https://www.googleapis.com/auth/analytics",
aud = "https://www.googleapis.com/oauth2/v3/token",
iat = tTimes[0],
exp = tTimes[1],
};
JavaScriptSerializer ser = new JavaScriptSerializer();
// encoded header
var tHeaderSerialized = ser.Serialize(tHeader);
var tHeaderBytes = Encoding.UTF8.GetBytes(tHeaderSerialized);
var tHeaderEncoded = Convert.ToBase64String(tHeaderBytes);
// encoded claimset
var tClaimsetSerialized = ser.Serialize(tClaimset);
var tClaimsetBytes = Encoding.UTF8.GetBytes(tClaimsetSerialized);
var tClaimsetEncoded = Convert.ToBase64String(tClaimsetBytes);
// input
var tInput = tHeaderEncoded + "." + tClaimsetEncoded;
var tInputBytes = Encoding.UTF8.GetBytes(tInput);
X509Certificate2 tCertificate = tCertCollection[0];
// signiture
var tRSA = tCertificate.PrivateKey as RSACryptoServiceProvider;
var tCspParam = new CspParameters
{
KeyContainerName = tRSA.CspKeyContainerInfo.KeyContainerName,
KeyNumber = tRSA.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
Flags = CspProviderFlags.UseMachineKeyStore
};
var tAesCsp = new RSACryptoServiceProvider(1024, tCspParam) { PersistKeyInCsp = true };
var tSignatureBytes = tAesCsp.SignData(tInputBytes, "SHA256");
var tSignatureEncoded = Convert.ToBase64String(tSignatureBytes);
// jwt
var tJWT = tHeaderEncoded + "." + tClaimsetEncoded + "." + tSignatureEncoded;
HttpClient tClient = new HttpClient();
Dictionary<string, string> tPost = new Dictionary<string, string>
{
{"assertion", tJWT},
{"grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"}
};
FormUrlEncodedContent tContent = new FormUrlEncodedContent(tPost);
var tURI = "https://www.googleapis.com/oauth2/v3/token";
HttpResponseMessage tResult = tClient.PostAsync(tURI, tContent).Result;
TokenResponse tTokenObject = JsonConvert.DeserializeObject<TokenResponse>(tResult.Content.ReadAsStringAsync().Result);
this.SessionToken = tTokenObject.access_token;
}
tCertStore.Close();
我希望这对某人有所帮助。
编码愉快。
我正在使用此代码连接到 Google OAuth2.0,并且我正在使用 C# 库。
using (var tImpersonationContext = new ImpersonationContext(ConfigurationManager.AppSettings["ImpersonationDomain"], ConfigurationManager.AppSettings["ImpersonationUser"], ConfigurationManager.AppSettings["ImpersonationPassword"]))
{
string[] tScopes = new string[] { AnalyticsService.Scope.Analytics };
var tKeyFilePath = Path.Combine(System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]), String.Format("GoogleCertificates\{0}", this.OAuthKeyName));
var tServiceAccountEmail = this.OAuthServiceAccountEmail;
//loading the Key file
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable);
var tCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(tServiceAccountEmail)
{
Scopes = tScopes
}.FromCertificate(tCertificate));
if (tCredential.RequestAccessTokenAsync(CancellationToken.None).Result)
{
this.SessionToken = tCredential.Token.AccessToken;
}
}
在我的开发环境中,一切都运行得非常完美,但是当我将应用程序移至我的 Azurre 服务器时,出现了这个错误:
The system cannot find the file specified.
当我尝试执行这一行时:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable);
我确定路径是正确的,事实上,如果我在文件资源管理器中复制并粘贴路径,导入证书的向导就会启动。
我确定模拟有效,因为该行已被执行。
我试过改成:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.MachineKeySet);
或者这样:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.UserProtected | X509KeyStorageFlags.DefaultKeySet);
而且没有任何效果,事实上,我从该网站的其他问题中尝试的所有内容都没有效果。
如果有帮助,我假装在计划任务中使用的 Windows 应用程序可以从 Google 分析中获取数据。
有人知道为什么不能在 Azure 服务器上工作吗?
提前致谢。
更新:
我已尝试安装证书并将代码更改为:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.MachineKeySet);
但是现在我有这个错误:
Key not valid for use in specified state.
我已经更改了方法中的所有代码,现在可以正常工作了。
首先,您必须在证书下受信任的根证书颁发机构内的 MMC 管理器中安装证书,并且必须将其设置为本地计算机。
然后你只需要使用这个代码:
X509Store tCertStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
tCertStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection tCertCollection = tCertStore.Certificates.Find(X509FindType.FindByThumbprint, this.OAuthKeyFingerprint, false);
// Get the first cert with the thumbprint
if (tCertCollection.Count > 0)
{
// header
var tHeader = new { typ = "JWT", alg = "RS256" };
// claimset
var tTimes = GetExpiryAndIssueDate();
var tClaimset = new
{
iss = this.OAuthServiceAccountEmail,
scope = "https://www.googleapis.com/auth/analytics",
aud = "https://www.googleapis.com/oauth2/v3/token",
iat = tTimes[0],
exp = tTimes[1],
};
JavaScriptSerializer ser = new JavaScriptSerializer();
// encoded header
var tHeaderSerialized = ser.Serialize(tHeader);
var tHeaderBytes = Encoding.UTF8.GetBytes(tHeaderSerialized);
var tHeaderEncoded = Convert.ToBase64String(tHeaderBytes);
// encoded claimset
var tClaimsetSerialized = ser.Serialize(tClaimset);
var tClaimsetBytes = Encoding.UTF8.GetBytes(tClaimsetSerialized);
var tClaimsetEncoded = Convert.ToBase64String(tClaimsetBytes);
// input
var tInput = tHeaderEncoded + "." + tClaimsetEncoded;
var tInputBytes = Encoding.UTF8.GetBytes(tInput);
X509Certificate2 tCertificate = tCertCollection[0];
// signiture
var tRSA = tCertificate.PrivateKey as RSACryptoServiceProvider;
var tCspParam = new CspParameters
{
KeyContainerName = tRSA.CspKeyContainerInfo.KeyContainerName,
KeyNumber = tRSA.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
Flags = CspProviderFlags.UseMachineKeyStore
};
var tAesCsp = new RSACryptoServiceProvider(1024, tCspParam) { PersistKeyInCsp = true };
var tSignatureBytes = tAesCsp.SignData(tInputBytes, "SHA256");
var tSignatureEncoded = Convert.ToBase64String(tSignatureBytes);
// jwt
var tJWT = tHeaderEncoded + "." + tClaimsetEncoded + "." + tSignatureEncoded;
HttpClient tClient = new HttpClient();
Dictionary<string, string> tPost = new Dictionary<string, string>
{
{"assertion", tJWT},
{"grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"}
};
FormUrlEncodedContent tContent = new FormUrlEncodedContent(tPost);
var tURI = "https://www.googleapis.com/oauth2/v3/token";
HttpResponseMessage tResult = tClient.PostAsync(tURI, tContent).Result;
TokenResponse tTokenObject = JsonConvert.DeserializeObject<TokenResponse>(tResult.Content.ReadAsStringAsync().Result);
this.SessionToken = tTokenObject.access_token;
}
tCertStore.Close();
我希望这对某人有所帮助。
编码愉快。