【问题标题】:"Access is denied" when calling GoogleWebAuthorizationBroker.AuthorizeAsync调用 GoogleWebAuthorizationBroker.AuthorizeAsync 时“访问被拒绝”
【发布时间】:2015-03-04 14:11:34
【问题描述】:

服务器设置: ASP.NET 表单在 .net 4.5.1 集成管道上运行在服务器 2012 上的 iis8 上。

我正在尝试从谷歌的 GoogleWebAuthorizationBroker 获取凭据,但我不断收到“访问被拒绝”。

认为这可能是访问问题,我尝试创建内存中的 IDataStore(在此处输入)

internal class DummyData : IDataStore
    {
        internal class item
        {
            public string Key { get; set; }
            public string value { get; set; }
        }
        internal static List<item> pKeys = new List<item>();
        public async Task ClearAsync()
        {
            pKeys = new List<item>();
        }

        public async Task DeleteAsync<T>(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("Key MUST have a value");
            }
                var generatedKey = GenerateStoredKey(key, typeof(T));
            if (pKeys.Any(x => x.Key == generatedKey))
            {
                pKeys.Remove(pKeys.First(x => x.Key == generatedKey));
            }
        }

        public Task<T> GetAsync<T>(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("Key MUST have a value");
            }
                var generatedKey = GenerateStoredKey(key, typeof(T));
                var item = pKeys.FirstOrDefault(x => x.Key == generatedKey);
                T value = item == null ? default(T) : JsonConvert.DeserializeObject<T>(item.value);
                return Task.FromResult<T>(value);

        }

        public async Task StoreAsync<T>(string key, T value)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("Key MUST have a value");
            }

            using (var context = new Platform4AutoDB())
            {
                var generatedKey = GenerateStoredKey(key, typeof(T));
                string json = JsonConvert.SerializeObject(value);

                var item = pKeys.FirstOrDefault(x => x.Key == generatedKey);                    

                if (item == null)
                {
                    pKeys.Add(new item { Key = generatedKey, value = json });                        
                }
                else
                {
                    item.value = json;
                }
            }
        }

        private static string GenerateStoredKey(string key, Type t)
        {
            return string.Format("{0}-{1}", t.FullName, key);
        }
    }

我用来测试的基本调用如下:

public string Test()
    {
        var xStore = new DummyData();
        var pSecrect = p4_db.GoogleAccounts.FirstOrDefault(x => x.ClientID == m_nClientID);
        if (string.IsNullOrEmpty(pSecrect.V3ClientSecret))
        {
            return "You are not set up to upload you tube videos.";
        }

        UserCredential credential;
        Sec pSecret = new Sec();

        pSecret.Web.client_secret = pSecrect.V3ClientSecret;
        var json = new JavaScriptSerializer().Serialize(pSecret);

        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {
            credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,
                // This OAuth 2.0 access scope allows an application to upload files to the
                // authenticated user's YouTube channel, but doesn't allow other types of access.
                new[] { YouTubeService.Scope.YoutubeUpload },
                "user",
                CancellationToken.None,
                xStore
            ).Result;
        }
        return " ";
    }

客户端密码的检索是通过 EF6 进行的,并且没有问题。

在我的登台服务器上运行它时,我收到以下错误:

System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.AggregateException: One or more errors occurred. ---> System.ComponentModel.Win32Exception: Access is denied
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\test\default\Src\GoogleApis.Auth.DotNet4\OAuth2\GoogleWebAuthorizationBroker.cs:line 59

GoogleWebAuthorizationBroker 中的第 59 行是这样的:

return await AuthorizeAsyncCore(initializer, scopes, user, taskCancellationToken, dataStore)
            .ConfigureAwait(false)

AuthorizeAsyncCore 看起来像这样:

  private static async Task<UserCredential> AuthorizeAsyncCore(
        GoogleAuthorizationCodeFlow.Initializer initializer, IEnumerable<string> scopes, string user,
        CancellationToken taskCancellationToken, IDataStore dataStore = null)
    {
        initializer.Scopes = scopes;
        initializer.DataStore = dataStore ?? new FileDataStore(Folder);
        var flow = new GoogleAuthorizationCodeFlow(initializer);

        // Create an authorization code installed app instance and authorize the user.
        return await new AuthorizationCodeInstalledApp(flow, new LocalServerCodeReceiver()).AuthorizeAsync
            (user, taskCancellationToken).ConfigureAwait(false);
    }

由于数据存储不为空,因此无论如何都不应该尝试访问磁盘。

有没有其他人在类似的环境中成功地实现了这一点,或者有任何其他想法?

【问题讨论】:

  • 我也遇到了同样的问题。代码在完全信任的情况下运行(不受限制)。

标签: asp.net google-api-dotnet-client


【解决方案1】:

我确实得到了这个工作 - 我的凭据块现在看起来像这样:`

UserCredential credential;            
        var pJ = new
        {
            web = new
             {
                 client_id = ConfigurationManager.AppSettings["YoutubeClientID"],
                 client_secret = ConfigurationManager.AppSettings["YoutubeClientSecret"], 
                 redirect_uris = ConfigurationManager.AppSettings["YouTubeClientRedirectUris"].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) 
             }
        };
        var json = new JavaScriptSerializer().Serialize(pJ);
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {
            credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,                 
                new[] { YouTubeService.Scope.Youtube },
                this.m_nClientID.ToString(),
                CancellationToken.None,
                pStore
            ).Result;
        }

我还 100% 确定在点击此之前我有一个有效的令牌 - 出于某种原因,当您的令牌无效时,dll 似乎默认为文件数据存储。

虽然这不是最好的解决方法,但它确实有效。

`

【讨论】:

  • 感谢分享。实际上,如果与您的代码相比,我认为您的代码没有根本区别 - 使用了相同的方法。 “访问被拒绝”的问题与 HttpListener 在执行 OAuth 握手时无法为普通用户抓取端口有关。
猜你喜欢
  • 2022-10-02
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多