如何将访问令牌从 .NET(代码隐藏)传递到 Javascript

How to pass an Access Token from .NET (code behind) to Javascript

我想 "authorize" 使用我自己的 API 密钥、秘密和刷新令牌通过 .NET 框架,然后传递 访问令牌 JavaScript 这样我就可以将带有进度指示器的视频直接上传到 YouTube。

我有 working code via the .NET API 可以 [未经授权] 直接完成上传到我的频道,但是你看不到任何进度指示(这可能需要相当长的时间)并且文件必须上传到我的服务器首先,然后到 YouTube 服务器。

服务器端访问代码与客户端访问代码是否不同?如果不是:

  1. 服务器端如何获取访问码?(获取字符串)
  2. *** 我如何通过 JavaScript 将其传递给 Google APIs? (不是<%= access code %>怎么写而是传到哪里?)

我很清楚公开访问令牌的安全风险,但这些确实会过期,对吗? (作为奖励,我怎样才能缩短过期时间)。这也是在受密码保护的网页内完成的,您不会得到 'client secret' 或 'refresh token'

***更新 - 我想我在 MediaUploader 对象中找到了传递令牌的位置。

var uploader = new MediaUploader({
        baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
        file: selectedFile,
        token: token, // ***RIGHT HERE***
        metadata: metadata,
        params: params,
        onError: function(data) {

好的,经过数周的 API、.NET 和 JavaScript 文档研究,我构建了以下解决方案....

按照 YouTube V3 Developer documentation 设置所有密钥。 (选择 OAuth、Web 应用程序,并为您的 Javascript 和重定向代码输入 URI)

接下来使用OAuth Playground获取您的刷新代码

一旦你拥有 client_id、client_secret 和 refresh_token,你就可以开始摇滚了!

这段代码通过后面的代码进行了一个简单的 HTTP/REST 调用,以获得一个 access_token,它可以持续 3600 秒(默认值)。然后它将此字符串传递给 JavaScript 代码以供使用 ****WARNING****

使用任何 .NET 或 JavaScript 库,只有一个文件除外,cors_upload.js available on GitHub

唉,代码
Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ApisCallTest.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta charset="utf-8" />
    <title>YouTube API Uploads via CORS</title>
    <style>
      #disclaimer {
        font-size: 0.75em;
        color: #aeaeae;
        max-width: 350px;
      }
      .during-upload { display: none; }
      label { display: block; }
      input[type="text"],
      textarea,
      progress {
        font-size: 16px;
        width: 15em;
        margin-bottom: 1em;
        padding: 0.5em;
        font-family: "Open Sans", sans-serif;
      }
    </style>
</head>
  <body>
    <div>
    <input input type="file" id="file" class="button" accept="video/*" />
    <button id="button">Upload Video</button>
    </div>
    <div class="during-upload">
    <p><span id="percent-transferred"></span>% done (<span id="bytes-transferred"></span>/<span id="total-bytes"></span> bytes)</p>
    <progress id="upload-progress" max="1" value="0"></progress>
    </div>
    <p id="disclaimer">By uploading a video, you certify that you own all rights to the content or that you are authorized by the owner to make the content publicly available on YouTube, and that it otherwise complies with the YouTube Terms of Service located at <a href="http://www.youtube.com/t/terms" target="_blank">http://www.youtube.com/t/terms</a></p>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="cors_upload.js"></script>
    <script>
      $('#button').on("click", goForUpload);
      function goForUpload() {
        if ($('#file').get(0).files[0]) {
          $('#button').attr('disabled', true);
          var uploadStartTime = 0;
          var metadata = {
            snippet: {
              title: 'PUT YOU TITLE HERE',
              description: 'THIS IS YOUR VIDEO DESCRIPTION',
              categoryId: '22'
            },
            status: {
              privacyStatus: 'unlisted'
            }
          };

          var uploader = new MediaUploader({
            baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
            file: $('#file').get(0).files[0],
            token: '<%= access_token %>',
            metadata: metadata,
            params: {
              part: Object.keys(metadata).join(',')
            },
            onError: function (data) {
              var message = data;
              // Assuming the error is raised by the YouTube API, data will be
              // a JSON string with error.message set. That may not be the
              // only time onError will be raised, though.
              try {
                var errorResponse = JSON.parse(data);
                message = errorResponse.error.message;
              } finally {
                alert(message);
              }
            },
            onProgress: function (data) {
              var currentTime = Date.now();
              var bytesUploaded = data.loaded;
              var totalBytes = data.total;
              // The times are in millis, so we need to divide by 1000 to get seconds.
              var bytesPerSecond = bytesUploaded / ((currentTime - this.uploadStartTime) / 1000);
              var estimatedSecondsRemaining = (totalBytes - bytesUploaded) / bytesPerSecond;
              var percentageComplete = (bytesUploaded * 100) / totalBytes;

              $('#upload-progress').attr({
                value: bytesUploaded,
                max: totalBytes
              });

              $('#percent-transferred').text(percentageComplete);
              $('#bytes-transferred').text(bytesUploaded);
              $('#total-bytes').text(totalBytes);

              $('.during-upload').show();
            },
            onComplete: function (data) {
              var uploadResponse = JSON.parse(data);
              alert('all done, you can store this id: ' + uploadResponse.id)
            }
          });
          uploadStartTime = Date.now();
          uploader.upload();
        }
      }
    </script>
  </body>
</html>

和Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace ApisCallTest
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        private static readonly HttpClient client = new HttpClient();
        public string access_token;
        protected void Page_Load(object sender, EventArgs e)
        {
            var values = new Dictionary<string, string>
            {
               { "client_id", "REPLACE_ME" },
               { "client_secret", "REPLACE_ME" },
               { "refresh_token", "REPLACE_ME" },
               { "grant_type", "refresh_token" }
            };

            var content = new FormUrlEncodedContent(values);
            var response = client.PostAsync("https://www.googleapis.com/oauth2/v4/token", content);
            string json = response.Result.Content.ReadAsStringAsync().Result;
            dynamic obj = JObject.Parse(json);
            access_token = obj.access_token;
        }
    }
}

结果...从受密码保护的网页,我可以让用户将视频上传到我的频道,不公开,并存储视频 ID,以便稍后将该视频嵌入回我的网站。

至于 ****警告****,这是一个安全问题,因为您正在(非常直接地)将您的个人访问密钥暴露给 "public"。它只持续 1 小时,但会提供您正在使用的任何 "scope" 访问权限 "anyone"这在公开页面上。