arrow_back

Como desenvolver aplicativos no Google Cloud: como adicionar autenticação e inteligência do usuário ao seu aplicativo

Acesse mais de 700 laboratórios e cursos

Como desenvolver aplicativos no Google Cloud: como adicionar autenticação e inteligência do usuário ao seu aplicativo

Laboratório 1 hora 30 minutos universal_currency_alt 5 créditos show_chart Intermediário
info Este laboratório pode incorporar ferramentas de IA para ajudar no seu aprendizado.
Acesse mais de 700 laboratórios e cursos

Visão geral

As bibliotecas de cliente do Cloud são o método recomendado para chamar as APIs do Google Cloud em aplicativos. Elas usam as convenções e o estilo naturais da linguagem de programação usada no aplicativo. As bibliotecas de cliente do Cloud lidam com a comunicação de baixo nível com o servidor, incluindo a lógica de autenticação e repetição.

O Firestore é um banco de dados de documentos NoSQL rápido, totalmente gerenciado e sem servidor, criado para fins de escalonamento automático, alto desempenho e facilidade de desenvolvimento de aplicativos.

As APIs do Google usam o protocolo OAuth 2.0 para autenticação e autorização.

O Secret Manager permite armazenar chaves de API, senhas, certificados e outros dados sensíveis como blobs binários ou strings de texto.

A API Cloud Translation permite que seus sites e aplicativos traduzam textos dinamicamente de maneira programática. O Cloud Translation pode traduzir textos para mais de 100 idiomas e detectar o idioma do texto de origem.

Neste laboratório, você vai usar a linguagem Python para criar um aplicativo que gerencia uma lista de livros. Você vai adicionar a capacidade de fazer login no aplicativo usando o OAuth e exige que o usuário faça login ao adicionar, editar ou excluir livros.

Você também vai usar a API Cloud Translation para traduzir as descrições dos livros para outro idioma. E adicionar um perfil de usuário que armazena o idioma de preferência dele.

O que você vai aprender

Neste laboratório, você vai aprender a:

  • Criar um aplicativo da Web simples com Python Flask.
  • Usar o Secret Manager para armazenar dados sensíveis de aplicativos.
  • Usar o OAuth 2.0 para adicionar o login do usuário a um aplicativo.
  • Usar a API Cloud Translation para detectar o idioma de um texto e traduzi-lo.

Configuração e requisitos

Antes de clicar no botão "Começar o laboratório"

Importante: leia estas instruções.

Os laboratórios são cronometrados e não podem ser pausados. O timer é iniciado quando você clica em Começar o laboratório e mostra por quanto tempo os recursos do Google Cloud vão ficar disponíveis.

Este laboratório prático do Qwiklabs permite que você realize as atividades em um ambiente real de nuvem, não em uma simulação ou demonstração. Você receberá novas credenciais temporárias para fazer login e acessar o Google Cloud durante o laboratório.

O que é necessário

Veja os requisitos para concluir o laboratório:

  • Acesso a um navegador de Internet padrão (recomendamos o Chrome)
  • Tempo disponível para concluir as atividades
Observação: não use seu projeto ou conta pessoal do Google Cloud neste laboratório. Observação: se você estiver usando um Pixelbook, faça o laboratório em uma janela anônima.

Como começar o laboratório e fazer login no console

  1. Clique no botão Começar o laboratório. Se for preciso pagar pelo laboratório, você verá um pop-up para selecionar a forma de pagamento. Um painel aparece à esquerda contendo as credenciais temporárias que você precisa usar no laboratório.

    Painel de credenciais

  2. Copie o nome de usuário e clique em Abrir console do Google. O laboratório ativa os recursos e depois abre a página Escolha uma conta em outra guia.

    Observação: abra as guias em janelas separadas, lado a lado.
  3. Na página "Escolha uma conta", clique em Usar outra conta. A página de login abre.

    Caixa de diálogo "Escolha uma conta" com a opção "Usar outra conta" destacada

  4. Cole o nome de usuário que foi copiado do painel "Detalhes da conexão". Em seguida, copie e cole a senha.

Observação: é necessário usar as credenciais do painel "Detalhes da conexão". Não use suas credenciais do Google Cloud Ensina. Não use sua conta pessoal do Google Cloud, caso tenha uma neste laboratório (isso evita cobranças).
  1. Acesse as próximas páginas:
  • Aceite os Termos e Condições.
  • Não adicione opções de recuperação nem autenticação de dois fatores (porque essa é uma conta temporária).
  • Não se inscreva em testes gratuitos.

Depois de alguns instantes, o console do Cloud abre nesta guia.

Observação: para acessar a lista dos produtos e serviços do Google Cloud, clique no Menu de navegação no canto superior esquerdo. Menu do console do Cloud

Ative o Google Cloud Shell

O Google Cloud Shell é uma máquina virtual com ferramentas de desenvolvimento. Ele tem um diretório principal permanente de 5 GB e é executado no Google Cloud.

O Cloud Shell oferece acesso de linha de comando aos recursos do Google Cloud.

  1. No console do Cloud, clique no botão "Abrir o Cloud Shell" na barra de ferramentas superior direita.

    Ícone do Cloud Shell em destaque

  2. Clique em Continuar.

O provisionamento e a conexão do ambiente podem demorar um pouco. Quando você estiver conectado, já estará autenticado, e o projeto estará definido com seu PROJECT_ID. Exemplo:

ID do projeto em destaque no terminal do Cloud Shell

A gcloud é a ferramenta de linha de comando do Google Cloud. Ela vem pré-instalada no Cloud Shell e aceita preenchimento com tabulação.

  • Para listar o nome da conta ativa, use este comando:
gcloud auth list

Saída:

Credentialed accounts: - @.com (active)

Exemplo de saída:

Credentialed accounts: - google1623327_student@qwiklabs.net
  • Para listar o ID do projeto, use este comando:
gcloud config list project

Saída:

[core] project =

Exemplo de saída:

[core] project = qwiklabs-gcp-44776a13dea667a6 Observação: a documentação completa da gcloud está disponível no guia com informações gerais sobre a gcloud CLI .

Tarefa 1: configurar o aplicativo Python e os recursos necessários

Nesta tarefa, você vai fazer o download do aplicativo Python e criar os recursos usados pela versão atual do app.

Observação: na maioria das linguagens, o recuo é usado para tornar o código mais legível. O Python usa o recuo para indicar um bloco de código, então o recuo precisa estar correto. O número de espaços usados no recuo precisa ser consistente. Misturar espaços e tabulações para recuo também pode causar problemas. Este laboratório usa quatro espaços para os recuos do Python.

Crie o banco de dados do Firestore

  1. Para criar o banco de dados do Firestore, execute o seguinte comando no Cloud Shell:

    gcloud firestore databases create --location={{{ project_0.default_region | region }}}

    O banco de dados do Firestore é usado para armazenar dados de livros e perfis de usuários.

  2. Se for solicitado que você autorize o Cloud Shell, clique em Autorizar.

Crie o bucket do Cloud Storage com as permissões corretas

  1. Para criar o bucket do Cloud Storage execute o seguinte comando:

    gcloud storage buckets create gs://{{{ project_0.project_id | project_id}}}-covers --location={{{ project_0.default_region | region }}} --no-public-access-prevention --uniform-bucket-level-access

    O bucket do Cloud Storage é usado para armazenar imagens de capa de livros. O bucket tem acesso uniforme no nível do bucket e não usa a prevenção de acesso público.

    Observação: se o comando falhar e o erro indicar que a conta não tem credenciais válidas, tente o comando novamente. As permissões da conta de estudante do Qwiklabs talvez ainda não tenham sido propagadas.
  2. Para tornar todos os objetos no bucket acessíveis publicamente, execute o comando a seguir:

    gcloud storage buckets add-iam-policy-binding gs://{{{ project_0.project_id | project_id}}}-covers --member=allUsers --role=roles/storage.legacyObjectReader

Para verificar o objetivo, clique em Verificar meu progresso. Configurar o aplicativo Python e os recursos necessários

Copie o código Python para o Cloud Shell

  1. Para copiar o código Python de um bucket do Cloud Storage para o diretório principal, execute o seguinte comando:

    gcloud storage cp gs://cloud-training/devapps-foundations/code/lab2/bookshelf.zip ~ && unzip ~/bookshelf.zip -d ~ && rm ~/bookshelf.zip
  2. Para verificar o conteúdo do diretório do app Bookshelf, execute o seguinte comando:

    cd ~ ls -R bookshelf

    Uma lista com três arquivos Python, um arquivo de requisitos e quatro arquivos de modelo vai aparecer:

    bookshelf: booksdb.py main.py requirements.txt storage.py templates bookshelf/templates: base.html form.html list.html view.html

Instale as dependências necessárias.

  1. Para listar as dependências no arquivo de requisitos, execute o seguinte comando:

    cat ~/bookshelf/requirements.txt

    O arquivo de requisitos especifica as seguintes dependências:

    • Flask: um módulo de framework da Web usado para projetar aplicativos da Web em Python
    • Gunicorn: um servidor HTTP Python que é executado no Linux
    • Cloud Logging: usado para registrar as informações do aplicativo
    • Firestore: um banco de dados de documentos NoSQL rápido, totalmente gerenciado e sem servidor, criado para facilitar o desenvolvimento de aplicativos
    • Cloud Storage: o armazenamento de objetos unificado do Google Cloud
  2. Para instalar as dependências no arquivo de requisitos, execute o seguinte comando:

    pip3 install -r ~/bookshelf/requirements.txt --user

    O utilitário pip é o instalador de pacotes de Python. O comando pip3 instala os pacotes especificados no arquivo requirements.txt para uso com a versão 3 do Python.

Testar o aplicativo

  1. Para iniciar o aplicativo, execute o seguinte comando:

    cd ~/bookshelf; ~/.local/bin/gunicorn -b :8080 main:app

    Se você criou os arquivos corretamente, o aplicativo vai estar hospedado na porta 8080.

  2. Para executar o aplicativo no navegador da Web, clique em Visualização da Web e selecione Visualizar na porta 8080.

    Visualizar na porta 8080

    Uma nova guia é aberta no navegador e o aplicativo é executado. Esta página mostra uma lista de todos os livros. Ainda não há livros.

    Observação: se for preciso autorizar o Cloud Shell, clique em Autorizar.
  3. Clique com o botão direito do mouse na imagem da capa do livro O Mágico de Oz e salve-a no computador como oz.png:

    Capa do livro O Mágico de Oz

  4. Na guia do aplicativo, clique em +Adicionar livro.

  5. Digite as seguintes informações no formulário:

    Campo Valor
    Título O Mágico de Oz
    Autor Frank L. Baum
    Data da publicação 1900
    Descrição Uma menina e seu cachorro são levados para uma terra mágica, onde encontram várias pessoas estranhas e aprendem a não ficar embaixo de casas.
  6. Em Imagem de capa, clique em Escolher arquivo.

  7. Selecione o arquivo que você baixou (oz.png) e clique em Abrir.

  8. Clique em Salvar.

    A página de visualização será aberta com os detalhes do livro.

  9. Na parte de cima da página, clique em Books.

    A página da lista será aberta, e O Mágico de Oz aparece na lista com a capa do livro. Os detalhes do livro são armazenados no banco de dados do Firestore, e a imagem da capa é armazenada no Cloud Storage.

    Observação: é possível adicionar outros livros, mas não modificar Oz. Ele será usado no restante deste laboratório.
  10. No Cloud Shell, para sair do aplicativo, pressione CTRL+C.

Para verificar o objetivo, clique em Verificar meu progresso. Teste o aplicativo e crie um livro

Tarefa 2: criar credenciais de autorização do OAuth para seu aplicativo

Nesta tarefa, você vai criar credenciais de autorização que identificam seu aplicativo para o servidor OAuth 2.0 do Google.

Crie a tela de permissão OAuth

Quando você usa o OAuth 2.0 para autorização, seu app solicita autorizações para um ou mais escopos de acesso de uma Conta do Google. O Google exibe uma tela de permissão ao usuário a fim de capturar a permissão dele para compartilhar dados com o aplicativo.

  1. No console do Google Cloud, selecione o Menu de navegação (Ícone do menu de navegação) e depois APIs e serviços > Tela de permissão OAuth.

    Nesta página, você seleciona o tipo de usuários que vão usar seu aplicativo. Usuários internos são usuários dentro da sua organização. Usuários externos são todos aqueles com uma Conta do Google.

  2. Clique em Começar.

  3. Em Nome do app, insira Bookshelf.

  4. Em E-mail para suporte do usuário, selecione o e-mail do estudante.

  5. Clique em Próxima.

  6. Em Público-alvo, selecione Externo e clique em Próxima.

    Os usuários com uma conta de teste podem fazer login no app.

  7. No painel esquerdo das instruções do laboratório, copie o Nome de usuário.

    Copiar nome de usuário

  8. Em Endereços de e-mail, cole o nome de usuário copiado e clique em Próxima.

  9. Marque a caixa de seleção para aceitar a política de dados do usuário e clique em Continuar.

  10. Clique em Criar.

  11. No menu de navegação, clique em Branding.

  12. Clique em + Adicionar domínio.

  13. Na seção Domínios autorizados, em Domínio autorizado 1, insira cloudshell.dev.

    Quando o aplicativo está em execução no Cloud Shell, cloudshell.dev é o nome de domínio.

  14. Clique em Salvar.

  15. No menu de navegação, selecione Acesso aos dados.

    Em seguida, você precisa selecionar os escopos que serão solicitados aos usuários para o aplicativo. Os escopos indicam os tipos de dados particulares do usuário na Conta do Google que o aplicativo quer acessar.

    Há três tipos de escopos:

    • Escopos confidenciais exigem a verificação do Google antes que sejam exibidos ao usuário na tela de consentimento.
    • Escopos restritos incluem informações ainda mais sensíveis, de apps como o Gmail e o Drive, e podem exigir uma revisão mais extensa.
    • Escopos não sensíveis são menos sensíveis e não precisam de verificação pelo Google.
  16. Clique em Adicionar ou remover escopos.

    Uma lista de escopos é apresentada.

  17. No início da lista, selecione a caixa ao lado de openid.

  18. Em Filtro, digite userinfo.profile, pressione Enter e selecione a caixa ao lado do escopo .../auth/userinfo.profile.

  19. Em Filtro, desmarque o filtro userinfo.profile, insira contacts, pressione Enter e selecione a caixa do escopo .../auth/contacts.

  20. Clique em Atualizar.

    Devem ser exibidos dois escopos não sensíveis (openid e userinfo.profile) e um sensível (contacts).

    Observação: este laboratório não vai usar o escopo "contacts", mas ele é usado como exemplo. Seus aplicativos devem usar os escopos mínimos necessários.
  21. Clique em Salvar.

  22. No menu de navegação, clique em Público-alvo.

    Os usuários de teste são necessários quando os usuários são externos e o status de publicação está definido como Teste.

  23. Clique em + Adicionar usuários.

  24. No painel esquerdo das instruções do laboratório, copie o Nome de usuário novamente.

  25. No painel Adicionar usuários, cole o nome de usuário copiado na caixa e clique em Salvar.

Crie as credenciais do OAuth 2.0

  1. No menu de navegação, clique em Clientes e depois em + Criar cliente.

  2. Em Tipo de aplicativo, selecione Aplicativo da Web.

  3. Em Nome, insira Bookshelf.

  4. Para URIs de redirecionamento autorizados, clique em + Adicionar URI.

    O URI especificado aqui será usado quando o Google redirecionar o navegador de volta ao aplicativo depois de capturar a permissão do usuário.

  5. Para acessar o URI de redirecionamento, execute o seguinte comando no Cloud Shell:

    echo "https://8080-${WEB_HOST}/oauth2callback"
  6. Copie o URI criado pelo comando echo e cole em URIs 1.

  7. Clique em Criar.

  8. Clique em Baixar o JSONe então salve o JSON da chave secreta do cliente na sua máquina local.

    O arquivo da chave secreta do cliente será usado para verificar seu app com o Google.

  9. Clique em Fechar.

  10. No Cloud Shell, clique em Mais (Ícone "Mais") na barra de ferramentas superior à direita e, em seguida, em Fazer upload.

  11. Clique em Escolher arquivos, selecione o arquivo JSON da chave secreta do cliente e clique em Abrir.

  12. Clique em Fazer upload.

    O arquivo JSON da chave secreta do cliente agora está disponível no diretório principal. O conteúdo desse arquivo será usado durante o processo do OAuth.

  13. No Cloud Shell, execute este comando:

    cat ~/client_secret_*.json

    Os conteúdos JSON incluem o client_secret, que deve ser tratado como uma senha. Por exemplo, nunca armazene esse arquivo JSON em um repositório de código.

Armazene o JSON da chave secreta do cliente no Secret Manager

O Secret Manager é um local seguro e recomendado para armazenar o arquivo JSON da chave secreta do cliente.

  1. Para ativar a API Secret Manager, execute o seguinte comando:

    gcloud services enable secretmanager.googleapis.com
  2. Para renomear o arquivo da chave secreta do cliente, execute o seguinte comando:

    mv ~/client_secret*.json ~/client_secret.json
  3. Para criar a chave secreta, execute o seguinte comando:

    gcloud secrets create bookshelf-client-secrets --data-file=$HOME/client_secret.json

    Agora há uma chave secreta chamada bookshelf-client-secrets que pode ser acessada pelo aplicativo.

    Outro valor secreto que é necessário para o aplicativo é a chave secreta do Flask, que é usada para assinar informações em cookies.

  4. Para criar uma chave secreta para a chave secreta do Flask, execute o seguinte comando:

    tr -dc A-Za-z0-9 </dev/urandom | head -c 20 | gcloud secrets create flask-secret-key --data-file=-

    Esse comando cria uma senha aleatória de 20 caracteres alfanuméricos e a armazena em uma chave secreta chamada flask-secret-key.

Para verificar o objetivo, clique em Verificar meu progresso. Criar credenciais de autorização do OAuth para seu aplicativo

Tarefa 3: usar o Secret Manager para recuperar chaves secretas no aplicativo

Nesta tarefa, você vai modificar o aplicativo para usar o Secret Manager.

Modifique o arquivo de requisitos para adicionar o Secret Manager

  1. Abra o arquivo requirements.txt com nano usando o seguinte comando:

    nano ~/bookshelf/requirements.txt
  2. No arquivo de requisitos, use a seta para baixo para ir até a primeira linha vazia e adicione isto:

    google-cloud-secret-manager==2.24.0

    O arquivo requirements.txt deve ficar assim:

    Flask==3.1.1 gunicorn==23.0.0 google-cloud-logging==3.12.1 google-cloud-firestore==2.21.0 google-cloud-storage==2.17.0 google-cloud-secret-manager==2.24.0
  3. Para salvar o arquivo e sair, pressione CTRL+X, Y e Enter.

  4. Para instalar as versões atualizadas das dependências, execute o seguinte comando:

    pip3 install -r ~/bookshelf/requirements.txt --user

Criar uma função para recuperar chaves secretas

O arquivo secrets.py contém o código para recuperar chaves secretas do Secret Manager.

  1. Para criar o arquivo secrets.py, execute o seguinte comando:

    cat > ~/bookshelf/secrets.py <<EOF import os from google.cloud import secretmanager def get_secret(secret_id, version_id='latest'): # create the secret manager client client = secretmanager.SecretManagerServiceClient() # build the resource name of the secret version project_id = os.getenv('GOOGLE_CLOUD_PROJECT') name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}" # access the secret version response = client.access_secret_version(name=name) # return the decoded secret return response.payload.data.decode('UTF-8') EOF

    A função get_secret() aceita um ID de chave secreta e um ID de versão opcional. A função retorna a chave secreta solicitada.

Modificar o main.py para usar o Secret Manager

O arquivo de código principal precisa chamar o Secret Manager para recuperar chaves secretas.

  1. Em um editor de arquivos, abra ~/bookshelf/main.py.

  2. Depois da importação para storage, adicione a seguinte linha:

    import secrets

    Essa linha importa o arquivo secrets.py que você acabou de criar.

  3. Na chamada de função app.config.update, mude a SECRET_KEY de:

    SECRET_KEY='secret', # don't store SECRET_KEY in code in a production app

    para:

    SECRET_KEY=secrets.get_secret('flask-secret-key'),

    A chave secreta do Flask não é mais armazenada no código do aplicativo.

  4. Salve o arquivo.

Tarefa 4: criar funções para o fluxo do OAuth

Nesta tarefa, você vai adicionar funções que gerenciam o fluxo de login do OAuth.

Quando um usuário faz login no aplicativo da Web, o app inicia a sequência de autorização do OAuth. O OAuth permite que o usuário autentique e conceda o acesso solicitado pelo aplicativo. A sequência de autorização do OAuth é assim:

Sequência de autorização do OAuth

A sequência de autorização começa quando o aplicativo redireciona o navegador para um URL do Google. O Google gerencia a autenticação do usuário, a seleção de sessão e o consentimento do usuário. O resultado é um código de autorização, que o aplicativo pode trocar por um token de acesso e um token de atualização.

O aplicativo armazena o token de atualização para uso futuro e usa o token de acesso para acessar as APIs do Google. O aplicativo Bookshelf chama uma API Google para recuperar informações sobre o usuário. Quando o token de acesso expira, o aplicativo usa o token de atualização para conseguir um novo.

Adicionar dependências

O cliente OAuth do Python para o Google precisa de mais três pacotes do Python.

  1. No arquivo ~/bookshelf/requirements.txt, adicione estas linhas:

    google-api-python-client==2.178.0 google-auth==2.40.3 google-auth-oauthlib==1.2.2

    O arquivo requirements.txt deve ficar assim:

    Flask==3.1.1 gunicorn==23.0.0 google-cloud-logging==3.12.1 google-cloud-firestore==2.21.0 google-cloud-storage==2.17.0 google-cloud-secret-manager==2.24.0 google-api-python-client==2.178.0 google-auth==2.40.3 google-auth-oauthlib==1.2.2
  2. Salve o arquivo.

  3. Para instalar as versões atualizadas das dependências, execute o seguinte comando:

    pip3 install -r ~/bookshelf/requirements.txt --user

Adicionar funções do OAuth para gerenciar o fluxo de autorização

O arquivo oauth.py contém o código para recuperar um token do OAuth do Google.

  1. Para criar o arquivo oauth.py, execute o seguinte comando:

    cat > ~/bookshelf/oauth.py <<EOF import google.oauth2.credentials import google_auth_oauthlib.flow from uuid import uuid4 from googleapiclient.discovery import build from werkzeug.exceptions import Unauthorized def _credentials_to_dict(credentials): """ Convert credentials mapping (object) into a dictionary. """ return { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes, 'id_token': credentials.id_token, } def authorize(callback_uri, client_config, scopes): """ Builds the URL that will be used for redirection to Google to start the OAuth flow. """ # specify the flow configuration details flow = google_auth_oauthlib.flow.Flow.from_client_config( client_config=client_config, scopes=scopes, ) flow.redirect_uri = callback_uri # create a random state state = str(uuid4()) # get the authorization URL authorization_url, state = flow.authorization_url( # offline access allows access token refresh without reprompting the user # using online here to force log in access_type='online', state=state, prompt='consent', include_granted_scopes='false', ) return authorization_url, state def handle_callback(callback_uri, client_config, scopes, request_url, stored_state, received_state): """ Fetches credentials using the authorization code in the request URL, and retrieves user information for the logged-in user. """ # validate received state if received_state != stored_state: raise Unauthorized(f'Invalid state parameter: received={received_state} stored={stored_state}') # specify the flow configuration details flow = google_auth_oauthlib.flow.Flow.from_client_config( client_config=client_config, scopes=scopes ) flow.redirect_uri = callback_uri # get a token using the details in the request flow.fetch_token(authorization_response=request_url) credentials = flow.credentials oauth2_client = build('oauth2','v2',credentials=credentials, cache_discovery=False) user_info = oauth2_client.userinfo().get().execute() return _credentials_to_dict(credentials), user_info EOF

    A função authorize() inicia a sequência de autorização. Ela configura o fluxo usando o parâmetro client_config, que será criado com base na string JSON de configuração do OAuth armazenada como um secret. O callback_uri especifica para onde o Google vai ligar com o código de autorização. Esse URI precisa corresponder a um URI configurado como um URI de redirecionamento autorizado para o aplicativo Bookshelf. A chamada flow.authorization_url() cria o URL completo para o redirecionamento ao Google. Um estado é criado e passado, e ele é armazenado na sessão para corresponder a chamada ao eventual callback. O URL e o estado de autorização são retornados ao autor da chamada.

    A função handle_callback() é usada quando o callback é recebido do Google. O estado especificado no URL de retorno precisa corresponder ao estado armazenado enviado no URL de autorização. A chamada flow.fetch_token() pode ser usada para buscar as credenciais, incluindo os tokens de acesso e de atualização. As credenciais retornadas são usadas para chamar o Google e receber informações do usuário conectado. As credenciais e as informações do usuário são retornadas ao chamador.

    Observação: a linha oauth2_client.userinfo() pode mostrar uma mensagem de erro no seu IDE indicando que não há um membro userinfo. O objeto Resource é retornado por build(), e os membros válidos não são conhecidos no tempo de compilação. Esse erro pode ser ignorado.

Tarefa 5: adicionar endpoints de login, retorno de chamada e logout

Nesta tarefa, você vai usar as funções do OAuth que acabou de criar para implementar endpoints de login, logout e retorno de chamada.

Modificar os modelos HTML

  1. Para criar um modelo de erro, execute o seguinte comando:

    cat > ~/bookshelf/templates/error.html <<EOF {% extends "base.html" %} {% block content %} <h3>Error: {{error_message}}</h3> {% endblock %} EOF

    Ao fazer login, o usuário pode encontrar um erro. Essa página será usada para exibir o erro.

  2. Em um editor de arquivos, abra o arquivo ~/bookshelf/templates/base.html.

    Os links de login e logout serão adicionados ao aplicativo.

  3. Na seção navbar, na linha após a tag de fechamento (/ul) da lista não ordenada (ul) com class="nav navbar-nav", adicione a seguinte seção:

    <ul class="nav navbar-nav navbar-right"> {% if session['credentials'] %} <div class="navbar-brand">{{session['user'].email}}</div> <div class="navbar-brand"><a href="/logout">Logout</a></div> {% else %} <div class="navbar-brand"><a href="/login">Login</a></div> {% endif %} </ul>

    O arquivo vai ficar assim:

    <!DOCTYPE html> <html lang="en"> <head> <title>Bookshelf</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> </head> <body> <div class="navbar navbar-default"> <div class="container"> <div class="navbar-header"> <div class="navbar-brand">Bookshelf</div> </div> <ul class="navbar-nav"> <li><a href="/">Books</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if session['credentials'] %} <div class="navbar-brand">{{session['user'].email}}</div> <div class="navbar-brand"><a href="/logout">Logout</a></div> {% else %} <div class="navbar-brand"><a href="/login">Login</a></div> {% endif %} </ul> </div> </div> <div class="container"> {% block content %}{% endblock %} </div> </body> </html>

    O modelo base agora usa a sessão para verificar se o usuário fez login. Se o usuário estiver conectado, o endereço de e-mail dele e um link para fazer logout serão exibidos. Se o usuário não estiver conectado, um link de login será mostrado.

  4. Salve o arquivo.

Modificar importações

  1. Em um editor de arquivos, abra ~/bookshelf/main.py.

  2. Adicione session às importações do flask.

    As importações do Flask vão ficar assim:

    from flask import current_app, Flask, redirect, render_template from flask import request, url_for, session

    Uma sessão vai fornecer acesso às informações associadas ao usuário conectado. Os dados da sessão serão armazenados em cookies.

  3. Depois da linha import cloud_logging, adicione as linhas a seguir:

    import json import os from urllib.parse import urlparse

    Em main.py, a biblioteca json é usada para converter a string de chave secreta do cliente em um mapeamento (objeto), e a biblioteca os é usada para utilizar variáveis de ambiente. A função urlparse() será usada para substituir o esquema e o nome do host em um URL.

  4. Depois da importação dos secrets, adicione a seguinte linha:

    import oauth

    Isso importa as funções do OAuth que você criou.

Adicionar itens de configuração

  1. Na chamada de função app.config.update(), adicione as linhas a seguir depois da linha ALLOWED_EXTENSIONS:

    CLIENT_SECRETS=json.loads(secrets.get_secret('bookshelf-client-secrets')), SCOPES=[ 'openid', 'https://www.googleapis.com/auth/contacts.readonly', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', ], EXTERNAL_HOST_URL=os.getenv('EXTERNAL_HOST_URL'),

    Os seguintes itens de configuração são adicionados:

    • CLIENT_SECRETS contém um mapeamento (objeto) para a configuração do OAuth armazenada no Secret Manager.
    • SCOPES contém uma lista de escopos a serem solicitados.
    • EXTERNAL_HOST_URL é usado para determinar o URL de retorno de chamada. Quando você usa a Visualização da Web com o Cloud Shell, o aplicativo definido para ser executado como localhost (127.0.0.1) na porta 80 é exposto à Internet em https://8080-...-cloudshell.dev. Esse URL será usado para converter o URL localhost do endpoint de retorno de chamada em um URL acessível publicamente. O valor será transmitido como uma variável de ambiente.

Adicionar endpoints e funções de suporte

  1. Depois da função log_request() (que começa com def log_request():), adicione as seguintes funções:

    def logout_session(): """ Clears known session items. """ session.pop('credentials', None) session.pop('user', None) session.pop('state', None) session.pop('error_message', None) session.pop('login_return', None) return def external_url(url): """ Cloud Shell routes https://8080-***/ to localhost over http This function replaces the localhost host with the configured scheme + hostname """ external_host_url = current_app.config['EXTERNAL_HOST_URL'] if external_host_url is None: # force https if url.startswith('http://'): url = f"https://{url[7:]}" return url # replace the scheme and hostname with the external host URL parsed_url = urlparse(url) replace_string = f"{parsed_url.scheme}://{parsed_url.netloc}" new_url = f"{external_host_url}{url[len(replace_string):]}" return new_url @app.route('/error') def error(): """ Display an error. """ log_request(request) if "error_message" not in session: return redirect(url_for('.list')) # render error return render_template('error.html', error_message=session.pop('error_message', None)) @app.route("/login") def login(): """ Login if not already logged in. """ log_request(request) if not "credentials" in session: # need to log in current_app.logger.info('logging in') # get authorization URL authorization_url, state = oauth.authorize( callback_uri=external_url(url_for('oauth2callback', _external=True)), client_config=current_app.config['CLIENT_SECRETS'], scopes=current_app.config['SCOPES']) current_app.logger.info(f"authorization_url={authorization_url}") # save state for verification on callback session['state'] = state return redirect(authorization_url) # already logged in return redirect(session.pop('login_return', url_for('.list'))) @app.route("/oauth2callback") def oauth2callback(): """ Callback destination during OAuth process. """ log_request(request) # check for error, probably access denied by user error = request.args.get('error', None) if error: session['error_message'] = f"{error}" return redirect(url_for('.error')) # handle the OAuth2 callback credentials, user_info = oauth.handle_callback( callback_uri=external_url(url_for('oauth2callback', _external=True)), client_config=current_app.config['CLIENT_SECRETS'], scopes=current_app.config['SCOPES'], request_url=external_url(request.url), stored_state=session.pop('state', None), received_state=request.args.get('state', '')) session['credentials'] = credentials session['user'] = user_info current_app.logger.info(f"user_info={user_info}") return redirect(session.pop('login_return', url_for('.list'))) @app.route("/logout") def logout(): """ Log out and return to root page. """ log_request(request) logout_session() return redirect(url_for('.list'))

    A função logout_session() limpa as entradas de sessão conhecidas.

    A função external_url() substitui o esquema e o nome do host de um URL por um nome de host diferente para acesso externo. Se o nome do host de substituição não for especificado, a função vai garantir que o URL retornado use https.

    O endpoint /error é usado para exibir um erro.

    O endpoint /login verifica a sessão para saber se um usuário fez login. Um usuário está conectado se as credenciais estiverem armazenadas na sessão. Se o usuário não tiver feito login, oauth.authorize() será chamado para receber o URL e o estado de autorização para o redirecionamento ao Google. O estado é salvo na sessão e o navegador é redirecionado para o URL de autorização.

    O endpoint /oauth2callback é chamado pelo Google durante o processo de autorização. Se houver um erro, o processo não será concluído e o usuário será redirecionado para a página de erro. Se não houver erro, handle_callback() será chamado para recuperar o token e as informações do usuário. Ao final do processo, o usuário é redirecionado para a página anterior em que o login foi iniciado automaticamente ou para a página raiz (lista de livros) se não houver um local de retorno.

    O endpoint /logout faz o usuário sair da sessão removendo as credenciais e os dados dele, e retorna à página raiz.

Exija login ao adicionar, editar ou excluir livros

Um usuário pode navegar pelos livros na estante sem fazer login. No entanto, é importante que o usuário faça login antes de modificar os livros.

Quando um usuário tentar adicionar, editar ou excluir um livro sem fazer login, ele deve ser forçado a fazer login.

  1. Na função add(), logo após a chamada para log_request(), adicione as linhas a seguir:

    # must be logged in if "credentials" not in session: session['login_return'] = url_for('.add') return redirect(url_for('.login'))

    Em add(), se o usuário não estiver conectado, ele será redirecionado para a página de adição após fazer login.

  2. Na função edit(), logo após a chamada para log_request(), adicione as linhas a seguir:

    # must be logged in if "credentials" not in session: session['login_return'] = url_for('.edit', book_id=book_id) return redirect(url_for('.login'))

    Em edit(), se o usuário não estiver conectado, ele será redirecionado para a página de edição do livro após fazer login.

  3. Na função delete(), logo após a chamada para log_request(), adicione as seguintes linhas:

    # must be logged in if "credentials" not in session: session['login_return'] = url_for('.view', book_id=book_id) return redirect(url_for('.login'))

    Em delete(), se o usuário não estiver conectado, ele será redirecionado para a página de visualização do livro depois de fazer login.

  4. Salve o arquivo.

Testar o aplicativo

  1. Para iniciar o servidor HTTP, no Cloud Shell, execute o seguinte comando:

    cd ~/bookshelf; EXTERNAL_HOST_URL="https://8080-$WEB_HOST" ~/.local/bin/gunicorn -b :8080 main:app

    Há uma variável de ambiente sendo passada para o aplicativo:

    • EXTERNAL_HOST_URL especifica o esquema e o nome do host que devem ser usados no URL de retorno de chamada. Se essa variável de ambiente não for especificada, o redirect_uri passado ao Google no URL de autorização vai usar o nome do host que o aplicativo encontrar nos URLs de entrada: 127.0.0.1:8080, que é localhost. A Visualização na Web encaminha as solicitações do URL cloudshell.dev para localhost (http://127.0.0.1:8080).
    Observação: se for necessário autorizar o Cloud Shell, clique em Autorizar.
  2. Para abrir o aplicativo no navegador da Web, clique em Visualização da Web e selecione Visualizar na porta 8080.

    Visualizar na porta 8080

    Uma nova guia é aberta no navegador e o aplicativo é executado. O livro O Mágico de Oz vai aparecer. O usuário não está conectado.

  3. Clique em + Adicionar livro.

    É necessário fazer login para adicionar um livro. Por isso, escolha uma conta para fazer login com o Google:

    Escolher uma conta

  4. Clique no e-mail do estudante e depois em Continuar.

    O Google vai solicitar consentimento para qualquer escopo restrito ou não sensível que for solicitado. Nesse caso, o download de todos os contatos é um escopo sensível.

    Conseguir consentimento

  5. Clique em Permitir.

    Você volta para o aplicativo na página Adicionar livro. Você está conectado e seu e-mail aparece no canto superior direito. Se você consultar os registros no Cloud Shell, a chamada de retorno do Google será exibida:

    INFO:main:REQ: GET http://127.0.0.1:8080/oauth2callback?state=88789b07-2474-423f-b572-f5d4a3240ace&code=4g0AfJohXm0vtB2eYHnRaAeM8m-VCmnssg5YgrjoJstTLmHaVq8nlbJo5uzIS67NbWTXTOqDw&scope=email%20profile%20openid%20https://www.googleapis.com/auth/contacts.readonly%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=qwiklabs.net&prompt=consent

    O usuário consentiu com o acesso, então o parâmetro chamado code tem o código de autorização que foi posteriormente trocado pelas credenciais. Os escopos permitidos também são retornados.

  6. Clique em Livros e depois em + Adicionar livro.

    Você já fez login, então pode ir direto para a página Adicionar livro.

  7. Clique em Sair e depois em Fazer login.

  8. Clique no e-mail do estudante, depois em Continuar e, em seguida, em Cancelar.

    Você voltará para a página de erro. Confira os registros no Cloud Shell. A chamada de retorno feita pelo Google vai aparecer. Ela vai ser semelhante a isto:

    INFO:main:REQ: GET http://127.0.0.1:8080/oauth2callback?error=access_denied&state=72342071-c8dc-43be-8184-9f6bd6069cd5

    Nesse caso, o consentimento não foi fornecido, então o código de autorização não foi retornado e o aplicativo não pode receber as credenciais do usuário.

  9. No Cloud Shell, para sair do aplicativo, pressione CTRL+C.

Para verificar o objetivo, clique em Verificar meu progresso. adicionar endpoints de login, retorno de chamada e logout

Tarefa 6: criar funções para tradução

Nesta tarefa, você vai criar funções que usam a API Cloud Translation para detectar o idioma do texto e fazer traduções.

As chamadas para a API Cloud Translation usam as credenciais do aplicativo.

Adicionar dependência do Cloud Translation

O aplicativo requer outro pacote do Python.

  1. No arquivo ~/bookshelf/requirements.txt, adicione a seguinte linha:

    google-cloud-translate==3.21.1

    O arquivo requirements.txt deve ficar assim:

    Flask==3.1.1 gunicorn==23.0.0 google-cloud-logging==3.12.1 google-cloud-firestore==2.21.0 google-cloud-storage==2.17.0 google-cloud-secret-manager==2.24.0 google-api-python-client==2.178.0 google-auth==2.40.3 google-auth-oauthlib==1.2.2 google-cloud-translate==3.21.1
  2. Salve o arquivo.

  3. Para instalar as dependências atualizadas, execute o seguinte comando:

    pip3 install -r ~/bookshelf/requirements.txt --user

Adicionar funções de tradução

O arquivo translate.py contém o código para realizar a tradução.

  1. Para criar o arquivo translate.py, execute o seguinte comando:

    cat > ~/bookshelf/translate.py <<EOF import os from google.cloud import translate PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT') PARENT = f"projects/{PROJECT_ID}" supported_languages = None def get_languages(): """ Gets the list of supported languages. """ # use the global variable global supported_languages # retrieve supported languages if not previously retrieved if not supported_languages: client = translate.TranslationServiceClient() response = client.get_supported_languages( parent=PARENT, display_language_code='en', ) supported_languages = response.languages return supported_languages def detect_language(text): """ Detect the language of the supplied text. Retorna o idioma mais provável. """ client = translate.TranslationServiceClient() response = client.detect_language( parent=PARENT, content=text, ) return response.languages[0] def translate_text(text, target_language_code): """ Translate the text to the target language. """ client = translate.TranslationServiceClient() response = client.translate_text( parent=PARENT, contents=[text], target_language_code=target_language_code, ) return response.translations[0] EOF

    A função get_languages() recupera a lista de idiomas com suporte na API Cloud Translation. Cada idioma na lista contém um ID (language_code) e o texto de exibição (display_name).

    A função detect_language() detecta o idioma de uma string de texto.

    A função translate_language() traduz texto para um idioma especificado.

Tarefa 7: crie um perfil de usuário para seleção de idioma e tradução de descrições

Nesta tarefa, você vai criar um perfil de usuário para usuários conectados. É possível selecionar um idioma preferido para o usuário.

O perfil será armazenado em uma coleção do Firestore chamada profiles. Um perfil padrão com o inglês como idioma preferido será usado até que o usuário atualize o perfil.

Adicionar funções para ler e atualizar perfis

O arquivo profiledb.py contém o código para ler e atualizar os perfis de usuário. O endereço de e-mail do usuário será usado como a chave do perfil. Nesta implementação, o único item no perfil será o idioma preferido.

  1. Para criar o arquivo profiledb.py, execute o seguinte comando:

    cat > ~/bookshelf/profiledb.py <<EOF from google.cloud import firestore default_profile = { "preferredLanguage": "en" } def __document_to_dict(doc): if not doc.exists: return None doc_dict = doc.to_dict() doc_dict['id'] = doc.id return doc_dict def read(email): """ Return a profile by email. """ db = firestore.Client() # retrieve a profile from the database by ID profile_ref = db.collection("profiles").document(email) profile_dict = __document_to_dict(profile_ref.get()) # return empty dictionary if no profile if profile_dict is None: profile_dict = default_profile.copy() return profile_dict def read_entry(email, key, default_value=''): """ Return a profile entry by email and key. """ profile_dict = read(email) return profile_dict.get(key, default_value) def update(data, email): """ Update a profile, and return the updated profile's details. """ db = firestore.Client() # atualiza o perfil no banco de dados profile_ref = db.collection("profiles").document(email) profile_ref.set(data) return __document_to_dict(profile_ref.get()) EOF

    A função read() recupera um perfil de um usuário especificado. Se um perfil não for encontrado, uma cópia do perfil padrão será retornada.

    A função read_entry() retorna um único valor do perfil de um usuário. Se a chave não for encontrada no perfil do usuário, o valor padrão informado será retornado.

    A função update() cria ou substitui o perfil do usuário com os dados especificados.

Adicione o endpoint de perfil para visualizar e editar um perfil de usuário

  1. Para criar um novo modelo para o perfil de usuário em profile.html, execute o seguinte comando:

    cat > ~/bookshelf/templates/profile.html <<EOF {# [START form] #} {% extends "base.html" %} {% block content %} <h3>Profile for {{session['user']['email']}}</h3> <form method="POST" enctype="multipart/form-data"> <div class="form-group"> <label for="preferredLanguage">Preferred Language</label> <select id="preferredLanguage" name="preferredLanguage"> {% for l in languages %} {% if l.language_code == profile['preferredLanguage'] %} <option value="{{l.language_code}}" selected>{{l.display_name}}</option> {% else %} <option value="{{l.language_code}}">{{l.display_name}}</option> {% endif %} {% endfor %} </select> </div> <button type="submit" class="btn btn-success">Save</button> </form> {% endblock %} {# [END form] #} EOF

    Este modelo cria um formulário com um controle de seleção e um botão de envio. O controle de seleção é carregado com todos os idiomas transmitidos usando a variável de lista languages. O valor de cada entrada é o language_code, e o display_name é mostrado no controle de seleção. O idioma exibido inicialmente é o preferredLanguage especificado no perfil.

  2. Em um editor de arquivos, abra ~/bookshelf/main.py.

  3. Depois da importação para oauth, adicione as seguintes linhas:

    import translate import profiledb

    Isso importa os arquivos translate.py e profiledb.py que você acabou de criar.

  4. Para adicionar o endpoint /profile, adicione a seguinte função depois do endpoint /books/<book_id>/delete:

    @app.route('/profile', methods=['GET', 'POST']) def profile(): """ If GET, show the form to collect updated details for the user profile. If POST, update the profile based on the specified form. """ log_request(request) # must be logged in if "credentials" not in session: session['login_return'] = url_for('.profile') return redirect(url_for('.login')) # read existing profile email = session['user']['email'] profile = profiledb.read(email) # Save details if form was posted if request.method == 'POST': # get book details from form data = request.form.to_dict(flat=True) # update profile profiledb.update(data, email) session['preferred_language'] = data['preferredLanguage'] # return to root return redirect(url_for('.list')) # render form to update book return render_template('profile.html', action='Edit', profile=profile, languages=translate.get_languages())

    O perfil só pode ser acessado por usuários conectados. Por isso, o usuário é redirecionado para fazer login, se ainda não estiver conectado.

    O e-mail do usuário conectado é retirado das informações do usuário na sessão, e o perfil atual é lido.

    O perfil é renderizado usando o modelo profile.html.

    Depois que você clica no botão "Enviar", o perfil é atualizado no banco de dados, o idioma preferido do usuário é armazenado na sessão e o navegador é redirecionado para a página raiz.

  5. Salve o arquivo.

Acesse o perfil ao clicar no endereço de e-mail do usuário

  1. Em um editor de arquivos, abra o arquivo ~/bookshelf/templates/base.html.

  2. Nesse arquivo, mude a seguinte linha de:

    <div class="navbar-brand">{{session['user'].email}}</div>

    para:

    <div class="navbar-brand"><a href="/profile">{{session['user'].email}}</a></div>

    Isso muda o endereço de e-mail exibido para um link clicável que redireciona para o endpoint /profile.

  3. Salve o arquivo.

Traduzir a descrição na página de visualização

  1. Em um editor de arquivos, abra o arquivo ~/bookshelf/templates/view.html.

  2. Nesse arquivo, mude a seguinte linha de:

    <p class="book-description">{{book.description}}</p>

    para:

    {% if translation_language is not none %} <p class="book-description"><strong>Description ({{description_language}}): </strong>{{book.description}}</p> <p class="book-description"><strong>Translation ({{translation_language}}): </strong>{{translated_text}}</p> {% else %} <p class="book-description"><strong>Description: </strong>{{book.description}}</p> {% endif %}

    Se translation_language não for especificado, a descrição não será alterada. No entanto, se houver um idioma de tradução, o idioma da descrição original será exibido e a próxima linha vai mostrar a versão traduzida com o texto. O endpoint de visualização precisa transmitir essas informações extras.

  3. Salve o arquivo.

  4. Em um editor de arquivos, abra ~/bookshelf/main.py.

  5. Depois da função log_request() (que começa com def log_request():), adicione o código a seguir:

    # build a mapping of language codes to display names display_languages = {} for l in translate.get_languages(): display_languages[l.language_code] = l.display_name

    A função detect_language() retorna um código de idioma detectado, mas não um nome de exibição. Esse código cria um mapeamento do código de idioma para o nome de exibição. Ele será usado para exibir o idioma detectado no modelo de visualização.

  6. Substitua o código do endpoint de visualização inteira pelo seguinte:

    @app.route('/books/<book_id>') def view(book_id): """ Exibe os detalhes de um livro especificado. """ log_request(request) # retrieve a specific book book = booksdb.read(book_id) current_app.logger.info(f"book={book}") # defaults if logged out description_language = None translation_language = None translated_text = '' if book['description'] and "credentials" in session: preferred_language = session.get('preferred_language', 'en') # translate description translation = translate.translate_text( text=book['description'], target_language_code=preferred_language, ) description_language = display_languages[translation.detected_language_code] translation_language = display_languages[preferred_language] translated_text = translation.translated_text # render book details return render_template('view.html', book=book, translated_text=translated_text, description_language=description_language, translation_language=translation_language, )

    O código agora traduz a descrição do livro para o idioma preferido do usuário e passa a tradução e os idiomas para o modelo.

  7. Salve o arquivo.

Tarefa 8: testar o aplicativo

  1. Para iniciar o servidor HTTP, execute o seguinte comando:

    cd ~/bookshelf; EXTERNAL_HOST_URL="https://8080-$WEB_HOST" ~/.local/bin/gunicorn -b :8080 main:app
  2. Para abrir o aplicativo no navegador da Web, clique em Visualização da Web e selecione Visualizar na porta 8080.

    Visualizar na porta 8080

    Uma nova guia é aberta no navegador e o aplicativo é executado. O livro O Mágico de Oz vai aparecer.

    Observação: se for preciso autorizar o Cloud Shell, clique em Autorizar.
  3. Se o usuário não estiver conectado, clique em Fazer login e forneça o consentimento para fazer login.

    O endereço de e-mail agora é um link.

  4. Clique no endereço de e-mail.

    O perfil foi exibido. O controle de seleção de idioma deve mostrar English.

  5. Mude o Idioma preferencial para Swahili e clique em Salvar.

  6. Clique no livro O Mágico de Oz.

    A página de visualização agora contém a descrição original em inglês e a tradução para suaíli.

Para verificar o objetivo, clique em Verificar meu progresso. Testar o aplicativo

Parabéns!

Você modificou um aplicativo para usar o OAuth para fazer login dos usuários. Depois, você adicionou um perfil de usuário com um idioma preferencial e usou a API Cloud Translation para fornecer traduções de descrições de livros.

Próximas etapas/Saiba mais

Finalize o laboratório

Clique em Terminar o laboratório após a conclusão. O Google Cloud Ensina remove os recursos usados e limpa a conta por você.

Você vai poder avaliar sua experiência no laboratório. Basta selecionar o número de estrelas, digitar um comentário e clicar em Enviar.

O número de estrelas indica o seguinte:

  • 1 estrela = muito insatisfeito
  • 2 estrelas = insatisfeito
  • 3 estrelas = neutro
  • 4 estrelas = satisfeito
  • 5 estrelas = muito satisfeito

Feche a caixa de diálogo se não quiser enviar feedback.

Para enviar seu feedback, fazer sugestões ou correções, use a guia Suporte.

Copyright 2024 Google LLC. Todos os direitos reservados. Google e o logotipo do Google são marcas registradas da Google LLC. Todos os outros nomes de empresas e produtos podem ser marcas registradas das empresas a que estão associados.

Antes de começar

  1. Os laboratórios criam um projeto e recursos do Google Cloud por um período fixo
  2. Os laboratórios têm um limite de tempo e não têm o recurso de pausa. Se você encerrar o laboratório, vai precisar recomeçar do início.
  3. No canto superior esquerdo da tela, clique em Começar o laboratório

Usar a navegação anônima

  1. Copie o nome de usuário e a senha fornecidos para o laboratório
  2. Clique em Abrir console no modo anônimo

Fazer login no console

  1. Faça login usando suas credenciais do laboratório. Usar outras credenciais pode causar erros ou gerar cobranças.
  2. Aceite os termos e pule a página de recursos de recuperação
  3. Não clique em Terminar o laboratório a menos que você tenha concluído ou queira recomeçar, porque isso vai apagar seu trabalho e remover o projeto

Este conteúdo não está disponível no momento

Você vai receber uma notificação por e-mail quando ele estiver disponível

Ótimo!

Vamos entrar em contato por e-mail se ele ficar disponível

Um laboratório por vez

Confirme para encerrar todos os laboratórios atuais e iniciar este

Use a navegação anônima para executar o laboratório

Para executar este laboratório, use o modo de navegação anônima ou uma janela anônima do navegador. Isso evita conflitos entre sua conta pessoal e a conta de estudante, o que poderia causar cobranças extras na sua conta pessoal.