无法对最新的GDrive代码使用ApplyAuthenticationToRequest调用
本文关键字:ApplyAuthenticationToRequest 调用 代码 GDrive 最新 | 更新日期: 2023-09-27 18:17:33
我正在做一个GDrive项目,这是10个多月前写的。前面获取Drive服务对象的代码是
private OAuth2Authenticator<AssertionFlowClient> authenticator;
private DriveService GetService(String userEmail)
{
X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);
var provider = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
{
ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
Scope = DriveService.Scopes.Drive.GetStringValue(),
ServiceAccountUser = userEmail,
};
authenticator = new OAuth2Authenticator<AssertionFlowClient>(provider, AssertionFlowClient.GetState);
return new DriveService(new BaseClientService.Initializer() { Authenticator = authenticator, ApplicationName = "Random" });
}
随着最新的google drive api更改,我更改了代码以获取驱动器服务对象
private DriveService GetService(String userEmail)
{
X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(SERVICE_ACCOUNT_EMAIL)
{
Scopes = new[] { DriveService.Scope.Drive },
User = userEmail,
}.FromCertificate(certificate));
// Create the service.
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Random",
});
}
我也有以下代码下载文件
public void DownloadFile(string url, string fileName)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
//authenticator.ApplyAuthenticationToRequest(request);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
System.IO.Stream received = response.GetResponseStream();
using (System.IO.FileStream file = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
Util.CopyStream(received, file);
}
}
这里的问题是,由于OAuth2Authenticator已弃用,因此随着获得驱动器服务对象的最新更改,我无法调用"ApplyAuthenticationToRequest"调用。没有调用该函数,我得到一个异常,"System.Net。web异常:远程服务器返回一个错误:(401)Unauthorized"。随着最新的变化,我如何才能调用"ApplyAuthenticationToRequest"函数,使调用能够成功。该函数还在项目中的其他2个地方使用。有人能帮帮我吗?
显然对于service
来说也是可能的 var file = service.Files.Get(fileID).Execute();
var bytes = service.HttpClient.GetByteArrayAsync(file.DownloadUrl).Result;
你需要从google请求一个令牌。下面是从google
获取令牌的类public class GoogleJsonWebToken
{
public const string SCOPE_DRIVE_READONLY = "https://www.googleapis.com/auth/drive.readonly";
public const string SCOPE_DRIVE = "https://www.googleapis.com/auth/drive";
public static dynamic GetAccessToken(string clientIdEMail, string keyFilePath, string scope)
{
// certificate
var certificate = new X509Certificate2(keyFilePath, "notasecret");
// header
var header = new { typ = "JWT", alg = "RS256" };
// claimset
var times = GetExpiryAndIssueDate();
var claimset = new
{
iss = clientIdEMail,
scope = scope,
aud = "https://accounts.google.com/o/oauth2/token",
iat = times[0],
exp = times[1],
};
JavaScriptSerializer ser = new JavaScriptSerializer();
// encoded header
var headerSerialized = ser.Serialize(header);
var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
var headerEncoded = Convert.ToBase64String(headerBytes);
// encoded claimset
var claimsetSerialized = ser.Serialize(claimset);
var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded = Convert.ToBase64String(claimsetBytes);
// input
var input = headerEncoded + "." + claimsetEncoded;
var inputBytes = Encoding.UTF8.GetBytes(input);
// signiture
var rsa = certificate.PrivateKey as RSACryptoServiceProvider;
var cspParam = new CspParameters
{
KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2
};
var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false };
var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
var signatureEncoded = Convert.ToBase64String(signatureBytes);
// jwt
var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;
var client = new WebClient();
client.Encoding = Encoding.UTF8;
var uri = "https://accounts.google.com/o/oauth2/token";
var content = new NameValueCollection();
content["assertion"] = jwt;
content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";
string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content));
var result = ser.Deserialize<dynamic>(response);
return result;
}
private static int[] GetExpiryAndIssueDate()
{
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var issueTime = DateTime.UtcNow;
var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds;
return new[] { iat, exp };
}
}
对于下载本身,我使用这个
public static byte[] GetFile(string fileID, out string contenttype, out string filename)
{
DALParameter dalp = new DALParameter();
var gdEmail = dalp.GetParameter(INMDTO.Parameters.GoogleDriveLogin, INMDTO.ParametersLevel.General, 0);
var credential = GetCertificate();
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "tttt",
});
string path = AppDomain.CurrentDomain.BaseDirectory + "App_Data''";
string certFile = "gd.p12";
string fullcertpath = Path.Combine(path, certFile);
var email = gdEmail;
var auth = GoogleJsonWebToken.GetAccessToken(email, fullcertpath, GoogleJsonWebToken.SCOPE_DRIVE_READONLY);
var f = service.Files.Get(fileID).Execute();
contenttype = f.MimeType;
filename = f.OriginalFilename;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(f.DownloadUrl));
req.Headers.Add("Authorization", auth["token_type"] + " " + auth["access_token"]);
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream sourceStream = response.GetResponseStream(); // the ConnectStream
byte[] array;
using (var ms = new MemoryStream())
{
sourceStream.CopyTo(ms);
array = ms.ToArray();
}
return array;
}
return null;
}
这可能不是最好的解决方案,但它有效,我真的没有找到另一种方法来做它。希望这对你有所帮助。