1

私は、gapi.auth.authorize を介して OAuth 2.0 を使用して Google+ ユーザーを認証し、gapi.client.request を使用して Google Fusion Tables sqlGet クエリを実行するページを書いています。クエリは認証前は正常に実行されますが、認証後 30 秒以上実行すると 403 "Insufficient Permission" エラーで失敗します。

この問題は、次のページで示されています: https://googledrive.com/host/0B5Urq1jZb1MYSWloU3NTY2M4Qnc/test3b.htm

次の手順に従ってください。

  1. [クエリ] をクリックして、gapi.client.request Google Fusion Table SQL-get クエリを実行し、行数を返します。これは、ステップ 2 と 3 で OAuth が使用されるまで正常に実行されます。

  2. [OAuth を開始] をクリックして、Google+ に対して immediate:true 承認を実行します。現在 Google+ にサインインしている場合、ユーザー名と ID が 3 番目のボタンに表示されます。

  3. 3 番目のボタンに Google+ ユーザー名が表示されない場合は、ボタン (「承認」) をクリックして Google+ にサインインします。

  4. もう一度「クエリ」ボタンをクリックします。OAuth 認証から約 30 秒以内にクエリを押すと、クエリはエラーなしで実行されます。その後、クエリは 403 エラーで失敗します。なぜ?

デモページのソースは次のとおりです。

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0" />

    <title>Test3b</title>

    <style type="text/css">
    </style>

    <script src="scripts/jquery-1.10.2.min.js" type="text/javascript"></script>

    <script type="text/javascript">
        var g_domIsReady = false;
        var g_gapiIsReady = false;

        $(function () {
            log("@$(function())");
            g_domIsReady = true;
            start();
        });

        function gapiIsReady() {
            log("@gapiIsReady");
            g_gapiIsReady = true;
            start();
        }

        function start() {

            // Make sure both the gapi.client and the DOM (per jquery) are ready.

            if (!(g_gapiIsReady && g_domIsReady)) return;

            // Define members.

            log("@start - gapi and DOM are ready");

            var m_apiKey = "AIzaSyAvb0NHQMwyPbMJRtz2zRL4wTiVjZDiois";  // Points to Google account (including Google Drive) at paloalto@geodesy.net.
            var m_clientId = "868768273487-q295tdfr54uvo98v74891qakcr9ci0pf.apps.googleusercontent.com";
            var m_scopes = "https://www.googleapis.com/auth/plus.me";

            // Wire buttons.

            var queryButton = document.getElementById('query-button');
            queryButton.onclick = function () { runGetRequest(); return false; };
            var startOAuthButton = document.getElementById('startOAuth-button');
            startOAuthButton.onclick = function () { startOAuth(); return false; };

            // Set-up the gapi.

            gapi.client.setApiKey(m_apiKey);

            //----------------------------------------------------------------------------
            // gapi.client.request query functions.
            //----------------------------------------------------------------------------

            function runGetRequest() {
                log("@runGetRequest");
                var tableId = "1VZgvKyuh9uHXkQawpxg1MU8AlO8Mngl-sx7SP74";  // TR_TREE_E
                var sql = "select count(GID) from " + tableId + " where GID > 50000";
                var path = "/fusiontables/v1/query";
                var restRequest = gapi.client.request({
                    path: path,
                    params: { 'sql': sql }
                });
                restRequest.execute(jsonCallback);
            }

            function jsonCallback(json) {
                log("@jsonCallback");
                var output = JSON.stringify(json);
                log(output);
                alert(output);
            }

            //----------------------------------------------------------------------------
            // OAuth functions.
            //----------------------------------------------------------------------------

            function startOAuth() {

                log("@startOAuth");

                var authorizeButton = document.getElementById('authorize-button');
                window.setTimeout(checkAuth, 1);  // check auth in 1 ms

                function checkAuth() {
                    log("@checkAuth");
                    gapi.auth.authorize({
                        client_id: m_clientId,
                        scope: m_scopes,
                        immediate: true
                    }, handleAuthResult);
                }

                function handleAuthResult(authResult) {
                    log("@handleAuthResult");
                    if (authResult && !authResult.error) {
                        log("@handleAuthResult - authResult=true");
                        log(authResult);  // authResult is a token (with 3600 second expiration).
                        authorizeButton.disabled = true;
                        useAuthResults();
                    } else {
                        log("@handleAuthResult - authResult=false");
                        authorizeButton.disabled = false;
                        authorizeButton.onclick = handleAuthClick;
                    }
                }

                function handleAuthClick() {
                    log("@handleAuthClick");
                    gapi.auth.authorize({
                        client_id: m_clientId,
                        scope: m_scopes,
                        immediate: false
                    }, handleAuthResult);
                    return false;
                }

                function useAuthResults() {
                    log("@useAuthResults");
                    // Get the Google+ user's ID and name (member info).
                    gapi.client.load('plus', 'v1', function () {
                        log("@gapi.client.load callback");
                        var request = gapi.client.plus.people.get({ 'userId': 'me' });
                        request.execute(function (aInfo) {
                            log("@request.execute callback");
                            if (aInfo.code !== undefined) {
                                alert('Google+ API returned ' + aInfo.code + ': ' + aInfo.message);
                            } else {
                                // Here with successful sign-in.  Display the user name.
                                log('Google+ user id, name: ' + aInfo.id + ', ' + aInfo.displayName);
                                authorizeButton.value = aInfo.displayName + " +" + aInfo.id;
                            }
                        });
                    });
                }

            }
        }

        function log(msg) {
            if (console) console.log(msg);
        }
    </script>

    <script src="https://apis.google.com/js/client.js?onload=gapiIsReady" type="text/javascript"></script>

</head>

<body>
    <h1>Test3a</h1>
    <p>This pages demonstrates a problem I am having using gapi.client.request with gapi.auth.</p>

    <input type="button" id="query-button" value="Query"><br>
    <input type="button" id="startOAuth-button" value="Start OAuth"><br>
    <input type="button" id="authorize-button" value="Authorize"><br>

    <p>Steps...</p>
    <p>1. Click "Query" to run a gapi.client.request Google Fusion Table SQL-get query returning
    a count of rows.  This will run successfully until OAuth is used in steps 2 and 3.</p>
    <p>2. Click "Start OAuth" to run an immediate:true authorization against Google+.  If you
    are currently signed into Google+, your user name will be displayed in the third button.</p>
    <p>3. If your Google+ user name is not displayed in the third button, press it ("Authorize")
    and sign into Google+.</p>
    <p>4. Click the "Query" button again.  
    The query will run without error when pressed within about 30 seconds of OAuth authorization.
    After that, the query fails with a 403 error.  WHY?</p>
</body>

</html>

Fusion Tables クエリを有効にするためではなく、ユーザーごとのページの使用状況を追跡するために Google+ サインインを使用するつもりであることに注意してください。

私はOAuthとgapi.client.requestを初めて使用するので、これは私の単純な誤解かもしれません。
洞察をありがとう。

4

1 に答える 1

0

すべての答えが得られるわけではありませんが、参考になると思われるものを以下に示します。

  1. ユーザーが G+ でサインインする前に、gapi.client.request オブジェクトは各リクエストに「key=yourAPIKey」パラメーターを追加します。

  2. ユーザーが G+ でサインインした後、gapi.client.request オブジェクトは各リクエストに「key=yourAPIKey」パラメーターを追加し、各リクエスト「Authorization: Bearer ya.xxxxxx」ヘッダーを送信して、アクセスを表します。ログインしているユーザーのトークン。

403 が表示される理由は、アクセス トークンがサーバーに送信されているためだと思いますが、FusionTables データへのアクセスを承認するスコープがトークンに含まれていません。アクセス トークンが送信されない場合、この検証は実行されません。

ユーザーが所有するデータに実際にアクセスしたい場合は、gapi.auth.authorize 呼び出しに適切なスコープを含めて、アプリケーションがデータにアクセスできるようにすることにユーザーの同意を得る必要があります (例: " https://www. googleapis.com/auth/fusiontables ")。

ただし、特定のユーザーに代わってデータにアクセスしようとしているとは思わないので、本当にやりたいことは、Fusion Table API の呼び出し中に「Authorization」ヘッダーがまったく送信されないようにすることです。

ユーザーがログインしているときに、gapi.client.request ライブラリがそのヘッダーを送信しないようにする簡単な方法がわかりません。そのため、別の解決策として、代わりに、gapi.client.request ライブラリを使用しない HTTP オブジェクトを作成することが考えられます (たとえば、XMLHttpRequest を直接使用します) - 各リクエストに「key=yourAPIKey」を手動で含めます。

(私が説明できないのは、なぜ 30 秒間異なる動作が見られるのかということです...)

于 2013-07-11T06:25:19.540 に答える