我一直试图从MVC应用访问特定的Google云端硬盘帐户。我只需要MVC网络应用程序访问我的谷歌驱动器扫描几个文件,并根据谷歌驱动器的内容更改数据库。问题是当在IIS中运行时,无法对驱动器进行身份验证,因为GoogleWebAuthorizationBroker尝试打开浏览器,如果它是一个Windows应用程序,但似乎无法通过IIS执行此操作,即使它确实是服务器端。
理想情况下,我根本不需要对这个应用程序进行身份验证,但是如果它已经完成了,那么我该如何让它在IIS中运行?
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "MY_ID",
ClientSecret = "My_Secret"
},
new[] { DriveService.Scope.Drive },
"user",
CancellationToken.None, dataStore: new FileDataStore(Server.MapPath("~/app_data/googledata"))).Result;
答案 0 :(得分:7)
我让这个工作,能够让网站使用我的帐户访问谷歌驱动器,而无需用户登录或授权。
首先,请点击此链接以使Google API与MVC合作:
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web_applications
HomeController中的示例代码存在问题
public async Task IndexAsync(CancellationToken cancellationToken)
应该是:
public async Task<ActionResult> IndexAsync(CancellationToken cancellationToken)
之后,我创建了一个MemoryDataStore(参见最后的代码),这是对这里发布的MemoryDataStore稍作修改:
http://conficient.wordpress.com/2014/06/18/using-google-drive-api-with-c-part-2/
执行此操作后,请捕获您正在使用的帐户的刷新令牌,并在进行身份验证时将商店替换为此商店:
private static readonly IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = clientID,
ClientSecret = clientSecret
},
Scopes = new[] { DriveService.Scope.Drive },
//DataStore = new FileDataStore("Drive.Api.Auth.Store")
DataStore = new GDriveMemoryDataStore(commonUser, refreshToken)
});
此处,commonUser是您所选择的预定义用户ID。请确保修改GetUserID()方法以返回相同的commonUser:
public override string GetUserId(Controller controller)
{
return commonUser;
}
完成此操作后,Google云端硬盘将停止要求用户登录并授权该应用。
这是我的MemoryDataStore代码:
/// <summary>
/// Handles internal token storage, bypassing filesystem
/// </summary>
internal class GDriveMemoryDataStore : IDataStore
{
private Dictionary<string, TokenResponse> _store;
private Dictionary<string, string> _stringStore;
//private key password: notasecret
public GDriveMemoryDataStore()
{
_store = new Dictionary<string, TokenResponse>();
_stringStore = new Dictionary<string, string>();
}
public GDriveMemoryDataStore(string key, string refreshToken)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key");
if (string.IsNullOrEmpty(refreshToken))
throw new ArgumentNullException("refreshToken");
_store = new Dictionary<string, TokenResponse>();
// add new entry
StoreAsync<TokenResponse>(key,
new TokenResponse() { RefreshToken = refreshToken, TokenType = "Bearer" }).Wait();
}
/// <summary>
/// Remove all items
/// </summary>
/// <returns></returns>
public async Task ClearAsync()
{
await Task.Run(() =>
{
_store.Clear();
_stringStore.Clear();
});
}
/// <summary>
/// Remove single entry
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public async Task DeleteAsync<T>(string key)
{
await Task.Run(() =>
{
// check type
AssertCorrectType<T>();
if (typeof(T) == typeof(string))
{
if (_stringStore.ContainsKey(key))
_stringStore.Remove(key);
}
else if (_store.ContainsKey(key))
{
_store.Remove(key);
}
});
}
/// <summary>
/// Obtain object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public async Task<T> GetAsync<T>(string key)
{
// check type
AssertCorrectType<T>();
if (typeof(T) == typeof(string))
{
if (_stringStore.ContainsKey(key))
return await Task.Run(() => { return (T)(object)_stringStore[key]; });
}
else if (_store.ContainsKey(key))
{
return await Task.Run(() => { return (T)(object)_store[key]; });
}
// key not found
return default(T);
}
/// <summary>
/// Add/update value for key/value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task StoreAsync<T>(string key, T value)
{
return Task.Run(() =>
{
if (typeof(T) == typeof(string))
{
if (_stringStore.ContainsKey(key))
_stringStore[key] = (string)(object)value;
else
_stringStore.Add(key, (string)(object)value);
} else
{
if (_store.ContainsKey(key))
_store[key] = (TokenResponse)(object)value;
else
_store.Add(key, (TokenResponse)(object)value);
}
});
}
/// <summary>
/// Validate we can store this type
/// </summary>
/// <typeparam name="T"></typeparam>
private void AssertCorrectType<T>()
{
if (typeof(T) != typeof(TokenResponse) && typeof(T) != typeof(string))
throw new NotImplementedException(typeof(T).ToString());
}
}
答案 1 :(得分:2)
我不熟悉C#,但通用的OAuth答案是您需要请求刷新令牌(仅限一次,您可以在OAuth游乐场中执行此操作),然后将该令牌存储/嵌入您的某处服务器,因此您可以在服务器应用程序需要访问云端硬盘时使用它来请求访问令牌。
有关如何执行此操作的详细信息,请参阅How do I authorise an app (web or installed) without user intervention? (canonical ?)。您当然要么需要对C#库存储其令牌的方式进行反向工程,要么创建/修改使用手动获取的刷新令牌的等效项。
答案 2 :(得分:0)
我怀疑你要找的是Service account。一个服务帐户将允许您设置您的应用程序以访问您的谷歌驱动器,而无需您进行Autenticate。
Google API也支持服务帐户。与中的情景不同 客户端应用程序请求访问最终用户的数据, 服务帐户提供对客户端应用程序自己的数据的访问。
您可以在此处找到有关如何实施服务帐户的Google文档。 Google APIs Client Library for .NET : Service Account