Como gerenciar sessões com o Firestore

Veja neste tutorial como gerenciar sessões no App Engine.

Muitos aplicativos precisam gerenciar sessões de autenticação e preferências do usuário. O pacote kit de ferramentas da Web do Gorilla sessions vem com uma implementação baseada no sistema de arquivos para executar essa função. No entanto, essa implementação não é adequada para um aplicativo que pode ser veiculado de várias instâncias, porque a sessão gravada em uma instância pode ser diferente nas outras. O pacote gorilla/sessions também vem com uma implementação baseada em cookies. No entanto, essa implementação exige a criptografia de cookies e o armazenamento de toda a sessão no cliente, em vez de apenas um ID da sessão, que pode ser muito grande para alguns aplicativos.

Objetivos

  • Gravar o aplicativo.
  • Executar o aplicativo localmente.
  • Implantar o aplicativo no App Engine.

Custos

Neste tutorial, usamos os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem ser qualificados para uma avaliação gratuita.

Ao concluir este tutorial, exclua os recursos criados para evitar o faturamento contínuo. Para mais informações, consulte Como fazer a limpeza.

Antes de começar

  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. No Console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  3. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

  4. Ative a API Firestore.

    Ative a API

  5. Instale e inicialize o SDK do Cloud..
  6. Atualize os componentes gcloud:
    gcloud components update
  7. Prepare seu ambiente para desenvolvedores.

Como configurar o projeto

  1. Na janela de terminal, clone o repositório do app de amostra em sua máquina local:

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git
  2. Acesse o diretório que contém o código de amostra:

    cd golang-samples/getting-started/sessions

Como entender o app da Web

Esse aplicativo exibe saudações em idiomas diferentes para cada usuário. Os usuários retornantes são sempre recebidos no mesmo idioma.

Várias janelas de aplicativos exibindo uma saudação em idiomas diferentes.

Para que o app possa armazenar as preferências de um usuário, você precisa de uma maneira de armazenar informações sobre o usuário atual em uma sessão. Este aplicativo de amostra usa o Firestore para armazenar dados da sessão.

Você pode usar firestoregorilla, um armazenamento de sessões compatível com gorilla/sessions.

  1. O aplicativo inicia importando dependências, definindo um tipo app para conter um sessions.Store e um modelo HTML e definindo a lista de saudações.

    
    // Command sessions starts an HTTP server that uses session state.
    package main
    
    import (
    	"context"
    	"fmt"
    	"html/template"
    	"log"
    	"math/rand"
    	"net/http"
    	"os"
    
    	"cloud.google.com/go/firestore"
    	firestoregorilla "github.com/GoogleCloudPlatform/firestore-gorilla-sessions"
    	"github.com/gorilla/sessions"
    )
    
    // app stores a sessions.Store. Create a new app with newApp.
    type app struct {
    	store sessions.Store
    	tmpl  *template.Template
    }
    
    // greetings are the random greetings that will be assigned to sessions.
    var greetings = []string{
    	"Hello World",
    	"Hallo Welt",
    	"Ciao Mondo",
    	"Salut le Monde",
    	"Hola Mundo",
    }
    
  2. Em seguida, o aplicativo define uma função main, que cria uma nova instância app, registra o gerenciador de índice e inicia o servidor HTTP. A função newApp cria a instância app inicializando um sessions.Store com a função firestoregorilla.New.

    
    func main() {
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
    	if projectID == "" {
    		log.Fatal("GOOGLE_CLOUD_PROJECT must be set")
    	}
    
    	a, err := newApp(projectID)
    	if err != nil {
    		log.Fatalf("newApp: %v", err)
    	}
    
    	http.HandleFunc("/", a.index)
    
    	log.Printf("Listening on port %s", port)
    	if err := http.ListenAndServe(":"+port, nil); err != nil {
    		log.Fatal(err)
    	}
    }
    
    // newApp creates a new app.
    func newApp(projectID string) (*app, error) {
    	ctx := context.Background()
    	client, err := firestore.NewClient(ctx, projectID)
    	if err != nil {
    		log.Fatalf("firestore.NewClient: %v", err)
    	}
    	store, err := firestoregorilla.New(ctx, client)
    	if err != nil {
    		log.Fatalf("firestoregorilla.New: %v", err)
    	}
    
    	tmpl, err := template.New("Index").Parse(`<body>{{.views}} {{if eq .views 1.0}}view{{else}}views{{end}} for "{{.greeting}}"</body>`)
    	if err != nil {
    		return nil, fmt.Errorf("template.New: %v", err)
    	}
    
    	return &app{
    		store: store,
    		tmpl:  tmpl,
    	}, nil
    }
    
  3. O gerenciador de índice obtém a sessão do usuário, criando uma, se necessário. As novas sessões recebem um idioma aleatório e uma contagem de visualização de zero. Em seguida, a contagem de visualizações é aumentada em um, a sessão é salva e o modelo HTML grava a resposta.

    
    // index uses sessions to assign users a random greeting and keep track of
    // views.
    func (a *app) index(w http.ResponseWriter, r *http.Request) {
    	if r.RequestURI != "/" {
    		return
    	}
    
    	// name is a non-empty identifier for this app's sessions. Set it to
    	// something descriptive for your app. It is used as the Firestore
    	// collection name that stores the sessions.
    	name := "hello-views"
    	session, err := a.store.Get(r, name)
    	if err != nil {
    		// Could not get the session. Log an error and continue, saving a new
    		// session.
    		log.Printf("store.Get: %v", err)
    	}
    
    	if session.IsNew {
    		// firestoregorilla uses JSON, which unmarshals numbers as float64s.
    		session.Values["views"] = float64(0)
    		session.Values["greeting"] = greetings[rand.Intn(len(greetings))]
    	}
    	session.Values["views"] = session.Values["views"].(float64) + 1
    	if err := session.Save(r, w); err != nil {
    		log.Printf("Save: %v", err)
    		// Don't return early so the user still gets a response.
    	}
    
    	if err := a.tmpl.Execute(w, session.Values); err != nil {
    		log.Printf("Execute: %v", err)
    	}
    }
    

    Veja no diagrama a seguir como o Firestore gerencia as sessões do aplicativo do App Engine.

    Diagrama da arquitetura: usuário, App Engine, Firestore.

Como excluir sessões

O firestoregorilla não exclui sessões antigas ou expiradas. É possível excluir dados da sessão no Console do Google Cloud ou implementar uma estratégia de exclusão automática. Se você usar soluções de armazenamento para sessões como Memcache ou Redis, as sessões expiradas serão excluídas automaticamente.

Como executar no local

  1. Na sua janela de terminal, crie o sessions binário:

    go build
    
  2. Inicie o servidor HTTP:

    ./sessions
    
  3. Veja seu app no navegador da Web:

    Cloud Shell

    Na barra de ferramentas do Cloud Shell, clique em Visualização da Web Visualização da Web e selecione Visualizar na porta 8080.

    Máquina local

    No seu navegador, acesse http://localhost:8080

    Você verá uma das cinco saudações: "Hello World"," "Hallo Welt", "Hola mundo", "Salut le Monde" ou "Ciao Mondo". O idioma será alterado se você abrir a página em um navegador diferente ou no modo de navegação anônima. Veja e edite os dados da sessão no Console do Google Cloud.

    Sessões do Firestore no Console do Cloud

  4. Para interromper o servidor HTTP, pressione Control+C na janela do terminal.

Como implantar e executar no App Engine

Use o ambiente padrão do App Engine para criar e implantar um aplicativo que seja executado de forma confiável sob carga pesada e com grandes quantidades de dados.

Neste tutorial, o ambiente padrão do App Engine é usado para implantar o servidor.

O arquivo app.yaml contém a configuração do ambiente padrão do App Engine:

runtime: go112
  1. Implante o aplicativo no App Engine:

    gcloud app deploy
    
  2. No navegador, digite o seguinte URL:

    https://PROJECT_ID.REGION_ID.r.appspot.com

    Substitua:

A saudação agora é entregue por um servidor da Web em execução em uma instância do App Engine.

Como depurar o aplicativo

Se você não conseguir se conectar ao aplicativo do App Engine, verifique o seguinte:

  1. Verifique se os comandos de implantação gcloud foram concluídos com êxito e não geraram erros. Se houver erros (por exemplo, message=Build failed), corrija-os e tente implantar o aplicativo do App Engine novamente.
  2. No Console do Cloud, acesse a página visualizador de registros.

    Acesse a página do visualizador de registros

    1. Na lista suspensa Recursos selecionados recentemente, clique em Aplicativo App Engine e, em seguida, clique em Todos os module_id. Você verá uma lista de solicitações de quando visitou seu aplicativo. Caso contrário, verifique se você selecionou Todos os module_id na lista suspensa. Se você vir mensagens de erro impressas no Console do Cloud, verifique se o código do aplicativo corresponde ao código na seção sobre como gravar o app da Web.

    2. Verifique se a API do Cloud Firestore está ativada.

Limpar

Excluir o projeto

  1. No Console do Cloud, acesse a página Gerenciar recursos:

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

Excluir a instância do App Engine

  1. No Console do Cloud, acesse a página Versões do App Engine.

    Acessar "Versões"

  2. Marque a caixa de seleção da versão não padrão do app que você quer excluir.
  3. Para excluir a versão do app, clique em Excluir.

A seguir