ASP.net MVC:访问 Google GoogleWebAuthorizationBroker returns 访问被拒绝错误

ASP.net MVC: Accessing Google GoogleWebAuthorizationBroker returns access denied error

我正在尝试使用 asp.net MVC 项目中 ActionResult 中的以下代码将视频上传到我的 YouTube 帐户:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload([Bind(Include = " Title, Description")] HttpPostedFileBase uploadFile, Videos videos)
    { 
var credential = AuthYouTube();
YouTubeService youtubeService = new YouTubeService(new 

YouTubeService.Initializer()
                {
                    ApplicationName = "app-name",
                    HttpClientInitializer = credential
                });

// Do Stuff with the video here.
}}

AuthYouTube() 看起来像这样(同一个控制器):

 public UserCredential AuthYouTube()
    {
        string filePath = Server.MapPath("~/Content/YT/client_secret.json");
        UserCredential credential;
        try{

            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    // This OAuth 2.0 access scope allows for full read/write access to the
                    // authenticated user's account.
                    new[] { YouTubeService.Scope.Youtube },
                    "username@domain.com",
                    CancellationToken.None,
                    new FileDataStore(Server.MapPath("~/Content/YT"),true)
                ).Result;
            };
            return credential;
        }
        catch(EvaluateException ex)
        {
            Console.WriteLine(ex.InnerException);
            return null;
        }

    }

我已将我从 Google 开发者控制台下载的 client_secret.json 存储在 [项目]/Content/YT 中。 (也尝试在 /App_Data 文件夹中。

上传调试器时显示以下消息:

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ComponentModel.Win32Exception: Access is denied

错误发生的地方:

credential = GoogleWebAuthorizationBroker.AuthorizeAsync(

StackStrace:

[Win32Exception (0x80004005): Access is denied]
   Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +115
   Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task) +78
   Google.Apis.Auth.OAuth2.<AuthorizeAsync>d__1.MoveNext() in C:\Users\mdril\Documents\GitHub\google-api-dotnet-client\Src\GoogleApis.Auth.DotNet4\OAuth2\GoogleWebAuthorizationBroker.cs:59

[AggregateException: One or more errors occurred.]
   System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) +4472256
   Project.Controllers.VideosController.AuthYouTube() in d:\dev\Development\project\project\Controllers\VideosController.cs:133
   project.Controllers.VideosController.Upload(HttpPostedFileBase uploadFile, Videos videos) in d:\dev\project\project\Controllers\VideosController.cs:71

这是什么原因? - Google API? - 文件夹/IIS 权限?

更新 01-02-2016

会不会是 API 端的一些访问错误? 如果没有,请有人给我提供正确的 IIS 权限的步骤,在授予文件夹权限后仍然出现错误。

运行 以下代码确实在我的 App_Data 中按预期创建文件夹,但也 returns 相同的 'Access denied' 错误。该文件夹是空的。

        var path = HttpContext.Current.Server.MapPath("~/App_Data/Drive.Api.Auth.Store");

        // here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
        UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
                                                                                     , scopes
                                                                                     , userName
                                                                                     , CancellationToken.None
                                                                                     , new FileDataStore(path,true)).Result;

有人可以解释一下如何让它工作吗?

再次准备好文档后,我找到了访问 API 并将我的视频上传到 YouTube 的方法。我希望我能澄清我这样做的方式。

我是怎么做到的: https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web-applications-aspnet-mvc

创建回调控制器:

using Google.Apis.Sample.MVC4;

namespace Google.Apis.Sample.MVC4.Controllers
{
    public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
    {
        protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData
        {
            get { return new AppFlowMetadata(); }
        }
    }
}

创建class并填写凭据:

using System;
using System.Web.Mvc;    
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Mvc;
using Google.Apis.YouTube.v3;
using Google.Apis.Util.Store;

namespace Google.Apis.Sample.MVC4
{
    public class AppFlowMetadata : FlowMetadata
    {
        private static readonly IAuthorizationCodeFlow flow =
            new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets
                    {
                        ClientId = "PUT_CLIENT_ID_HERE",
                        ClientSecret = "PUT_CLIENT_SECRET_HERE"
                    },
                    Scopes = new[] { YouTubeService.Scope.YoutubeUpload },
                    DataStore = new FileDataStore(HttpContext.Current.Server.MapPath("~/App_Data/clientsecret.json")),
                });

        public override string AuthCallback
        {
             get { return @"/AuthCallback/Upload"; }
        }

        public override string GetUserId(Controller controller)
        {
            // In this sample we use the session to store the user identifiers.
            // That's not the best practice, because you should have a logic to identify
            // a user. You might want to use "OpenID Connect".
            // You can read more about the protocol in the following link:
            // https://developers.google.com/accounts/docs/OAuth2Login.
            var user = controller.Session["user"];
            if (user == null)
            {
                user = Guid.NewGuid();
                controller.Session["user"] = user;
            }
            return user.ToString();

        }

        public override IAuthorizationCodeFlow Flow
        {
            get { return flow; }
        }
    }
}

在我的 ActionResult 中,我设置了 YoutubeService。我的视频是在我的 Upload POST

中创建的

您自己的控制器(我的控制器用于 /upload 操作):

public async Task<ActionResult> Upload(CancellationToken cancellationToken)
        {
           var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);
            if (result.Credential != null)
            {
                var youtubeService = new YouTubeService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = result.Credential,
                    ApplicationName = "name",
                });
                return View();
            }
            else
            {
                return new RedirectResult(result.RedirectUri);
            }        
        }

上传逻辑见: https://developers.google.com/youtube/v3/code_samples/dotnet#upload_a_video

在 Google 开发者控制台中设置重定向 URL

在 Google 开发人员控制台中,将授权重定向 URI 值设置为类似(我的控制器称为视频):http://www.domainname.com/Videos/Upload

**使用单个 oAuth 帐户 **

为了在我的会话中保存客户端 ID(GUID,请参阅 AppFlowMetadata 文件中的 GetUserId),我现在使用一个 ID,这样我就可以为所有用户使用相同的 token/responsive。