使用用户帐号针对已安装的应用进行身份验证

本指南介绍了在您的应用已安装到用户机器上的情况下,如何使用用户帐号执行身份验证,以获得 BigQuery API 的访问权限。

如需确保应用仅访问最终用户可用的 BigQuery 表,请使用用户凭据进行身份验证。用户凭据只能对最终用户的 Google Cloud 项目(而非应用的项目)运行查询。因此,系统会按查询(而非应用)向用户收取费用。

准备工作

  1. 创建一个代表已安装的应用的 Google Cloud 项目
  2. 安装 BigQuery 客户端库
  3. 安装必需的库。

    Python

    安装用于 Google 身份验证的 oauthlib 集成
    pip install --upgrade google-auth-oauthlib

    Node.js

    安装用于 Google 身份验证的 oauthlib 集成
    npm install google-auth-library
    npm install readline-promise

设置您的客户端凭据

使用以下按钮选择项目并创建所需的凭据。

获取凭据

手动创建凭据

  1. 转到 Google Cloud Console 中的 API 凭据页面
  2. 填写 OAuth 同意屏幕中的必填字段。
  3. 凭据页面上,点击创建凭据按钮。

    选择 OAuth 客户端 ID

  4. 选择桌面设备作为应用类型,然后点击创建
  5. 点击下载 JSON 按钮以下载凭据。

    下载 JSON。

    将凭据文件保存到 client_secrets.json。此文件必须随应用一起分发。

API 的身份验证与调用

  1. 使用客户端凭据执行 OAuth 2.0 流程

    Python

    from google_auth_oauthlib import flow
    
    # TODO: Uncomment the line below to set the `launch_browser` variable.
    # launch_browser = True
    #
    # The `launch_browser` boolean variable indicates if a local server is used
    # as the callback URL in the auth flow. A value of `True` is recommended,
    # but a local server does not work if accessing the application remotely,
    # such as over SSH or from a remote Jupyter notebook.
    
    appflow = flow.InstalledAppFlow.from_client_secrets_file(
        'client_secrets.json',
        scopes=['https://www.googleapis.com/auth/bigquery'])
    
    if launch_browser:
        appflow.run_local_server()
    else:
        appflow.run_console()
    
    credentials = appflow.credentials

    Node.js

    const {OAuth2Client} = require('google-auth-library');
    const readline = require('readline-promise').default;
    
    function startRl() {
      const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
      });
    
      return rl;
    }
    
    /**
     * Download your OAuth2 configuration from the Google
     * Developers Console API Credentials page.
     * https://console.cloud.google.com/apis/credentials
     */
    const keys = require('./oauth2.keys.json');
    
    /**
     * Create a new OAuth2Client, and go through the OAuth2 content
     * workflow. Return the full client to the callback.
     */
    async function getRedirectUrl() {
      const rl = main.startRl();
      // Create an oAuth client to authorize the API call.  Secrets are kept in a `keys.json` file,
      // which should be downloaded from the Google Developers Console.
      const oAuth2Client = new OAuth2Client(
        keys.installed.client_id,
        keys.installed.client_secret,
        keys.installed.redirect_uris[0]
      );
    
      // Generate the url that will be used for the consent dialog.
      const authorizeUrl = oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: 'https://www.googleapis.com/auth/bigquery',
        prompt: 'consent',
      });
    
      console.info(
        `Please visit this URL to authorize this application: ${authorizeUrl}`
      );
    
      const code = await rl.questionAsync('Enter the authorization code: ');
      const tokens = await main.exchangeCode(code);
      rl.close();
    
      return tokens;
    }
    
    // Exchange an authorization code for an access token
    async function exchangeCode(code) {
      const oAuth2Client = new OAuth2Client(
        keys.installed.client_id,
        keys.installed.client_secret,
        keys.installed.redirect_uris[0]
      );
    
      const r = await oAuth2Client.getToken(code);
      console.info(r.tokens);
      return r.tokens;
    }
    
    async function authFlow(projectId = 'project_id') {
      /**
       * TODO(developer):
       * Save Project ID as environment variable PROJECT_ID="project_id"
       * Uncomment the following line before running the sample.
       */
      // projectId = process.env.PROJECT_ID;
    
      const tokens = await main.getRedirectUrl();
    
      const credentials = {
        type: 'authorized_user',
        client_id: keys.installed.client_id,
        client_secret: keys.installed.client_secret,
        refresh_token: tokens.refresh_token,
      };
    
      return {
        projectId,
        credentials,
      };
    }
  2. 使用经过身份验证的凭据连接到 BigQuery API。

    Python

    from google.cloud import bigquery
    
    # TODO: Uncomment the line below to set the `project` variable.
    # project = 'user-project-id'
    #
    # The `project` variable defines the project to be billed for query
    # processing. The user must have the bigquery.jobs.create permission on
    # this project to run a query. See:
    # https://cloud.google.com/bigquery/docs/access-control#permissions
    
    client = bigquery.Client(project=project, credentials=credentials)
    
    query_string = """SELECT name, SUM(number) as total
    FROM `bigquery-public-data.usa_names.usa_1910_current`
    WHERE name = 'William'
    GROUP BY name;
    """
    query_job = client.query(query_string)
    
    # Print the results.
    for row in query_job.result():  # Wait for the job to complete.
        print("{}: {}".format(row['name'], row['total']))

    Node.js

    async function query() {
      const {BigQuery} = require('@google-cloud/bigquery');
    
      const credentials = await main.authFlow();
      const bigquery = new BigQuery(credentials);
    
      // Queries the U.S. given names dataset for the state of Texas.
      const query = `SELECT name, SUM(number) as total
      FROM \`bigquery-public-data.usa_names.usa_1910_current\`
      WHERE name = 'William'
      GROUP BY name;`;
    
      // For all options, see https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query
      const options = {
        query: query,
      };
    
      // Run the query as a job
      const [job] = await bigquery.createQueryJob(options);
      console.log(`Job ${job.id} started.`);
    
      // Wait for the query to finish
      const [rows] = await job.getQueryResults();
    
      // Print the results
      console.log('Rows:');
      rows.forEach(row => console.log(row));
    
      return rows;
    }
    
    const main = {
      query,
      authFlow,
      exchangeCode,
      getRedirectUrl,
      startRl,
    };
    module.exports = {
      main,
    };
    
    if (module === require.main) {
      query().catch(console.error);
    }

当您运行示例代码时,它将启动一个浏览器,请求授予权限来访问与客户端密钥关联的项目。您可以使用所得到的凭据访问用户的 BigQuery 资源,因为示例代码请求的是 BigQuery 范围

后续步骤

  1. 了解对应用进行身份验证以访问 BigQuery API 的其他方式
  2. 了解如何使用最终用户凭据针对所有 Google Cloud APIs 进行身份验证