GoogleWebAuthorizationBroker在MVC为谷歌驱动器访问

本文关键字:驱动器 访问 谷歌 MVC GoogleWebAuthorizationBroker | 更新日期: 2023-09-27 17:51:25

我被困在试图从MVC应用程序访问一个特定的谷歌驱动器帐户。我所需要的是MVC web应用程序访问我的谷歌驱动器扫描几个文件,并根据谷歌驱动器的内容更改数据库。问题是当在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;

GoogleWebAuthorizationBroker在MVC为谷歌驱动器访问

我让这个工作,能够使网站访问谷歌驱动器使用我的帐户,而不要求用户登录或授权。

首先,按照这个链接来获得谷歌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;
    }

一旦这样做,谷歌驱动器将停止要求用户登录和授权应用程序。

这是我的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());
     }
 }

我不熟悉c#,但通用的OAuth答案是,你需要请求一个刷新令牌(只有一次,你可以在OAuth操场上这样做),然后存储/嵌入令牌在服务器的某个地方,这样你就可以使用它来请求访问令牌每当你的服务器应用程序需要访问驱动器。

参见如何在没有用户干预的情况下授权应用程序(web或已安装)?(canonical ?)以了解如何做到这一点的详细信息。当然,你要么需要逆向工程c#库如何存储它的令牌,要么创建/修改一个等效的使用手动获得的刷新令牌。

我怀疑你正在寻找的是一个服务帐户。一个服务帐户将允许你设置你的应用程序访问你的谷歌驱动器,而不需要你的身份验证。

Google api也支持服务帐户。不像客户端应用程序请求访问最终用户的数据,服务帐户提供对客户端应用程序自身数据的访问。

你可以在这里找到谷歌关于如何实现一个服务帐户的文档。.NET的Google api客户端库:Service Account