Alura > Cursos de Programação > Cursos de Node.JS > Conteúdos de Node.JS > Primeiras aulas do curso WebSockets: implemente autenticação e avance no Socket.IO

WebSockets: implemente autenticação e avance no Socket.IO

Cadastrando usuários - Apresentação

Olá e boas vindas ao segundo curso de WebSockets aqui da Plataforma Alura! Sou o instrutor Antonio Evaldo que te acompanhará ao longo das aulas.

Autodescrição: Sou um homem branco com cabelos compridos pretos e ondulados presos atrás da cabeça, uso cavanhaque, tenho olhos castanhos escuros e visto uma camiseta escura sem estampa. Ao fundo, está uma parede iluminada por uma luz azul e há um quadro pendurado com o desenho de uma guitarra vermelha.

Daremos continuidade ao AluraDocs que começamos no curso anterior, e nossas amigas fictícias, a Eduarda e a Juliana, nos pediram para fazer um sistema de cadastro de pessoas usuárias ou login para poderem convidar outras amigas e amigos para utilizar a aplicação também.

Página inicial do projeto AluraDocs no endereço de "localhost:3000/login/index.html" no navegador. O fundo é branco e, no topo, está o título "AluraDocs" escrito em preto com uma fonte fina e sem serifa. Abaixo, há o texto "Login" escrito do mesmo jeito, seguido do campo de texto em branco de legenda "Usuário". Abaixo, está outro campo de texto em branco com legenda "Senha". Abaixo, alinhado à esquerda, está o botão azul de bordas arredondadas com a legenda "Login" dentro. Por fim, na base dos elementos, está o texto "Não possui usuário?" em preto seguido de "faça o cadastro" como um link clicável escrito em azul e sublinhado.

Em nossa página inicial, já teremos cadastrado algumas pessoas e entraremos com "Evaldo" no campo "Usuário", por exemplo, com a senha "123" cadastrada.

Clicaremos no botão de "Login" e aparecerá no topo da tela uma mensagem do navegador dizendo "Usuário autenticado com sucesso!". Clicando em "Ok" nesta caixa de diálogo, nos redirecionaremos para a página inicial logada que já conhecemos.

Página inicial já logada do projeto AluraDocs ainda no endereço de "localhost:3000/login/index.html" no navegador. O fundo é branco e, no topo, está o título "AluraDocs" escrito em preto com uma fonte fina e sem serifa. Abaixo, há uma lista contendo três itens: "Node", "Socket.IO" e "JavaScript". Abaixo, há um campo com o placeholder "Documento..." e, ao lado direito dele, está o botão azul com o escrito "Adicionar documento" escrito em branco. No canto superior direito da página, está um botão azul de bordas arredondadas com a legenda "Logout" em branco.

No canto superior direito da tela, teremos o botão "Logout". Se clicarmos nele, receberemos outra mensagem do navegador indicando que "Usuário foi deslogado com sucesso!"

Se não logarmos no sistema e tentarmos acessar a página inicial deixando apenas "localhost:3000" na barra de endereço, iremos para a outra tela e receberemos a mensagem de "Error: JWT must be provided", ou seja, o "JWT deve ser fornecido" em português.

Portanto, já estamos conseguindo controlar os acessos ao AluraDocs, pois não conseguimos acessar a página inicial sem fazermos o login no sistema.

Implementaremos toda essa parte de cadastro, login e autorização de pessoas usuárias.

Para entendermos mais um aspecto que iremos trabalhar neste curso, abriremos a tela com os campos de texto de "Usuário" e "Senha" e faremos o login com os dados já cadastrados.

Na página inicial seguinte já logada, clicaremos em "Node" no primeiro item da lista e acessaremos a lista de pessoas conectadas ao documento.

Página dos documentos "Node" do projeto AluraDocs no endereço de "localhost:3000/documento/index.html?nome=Node" no navegador. O fundo é branco e, no topo, está o título "Node" escrito em preto com uma fonte fina e sem serifa. Abaixo e centralizada, há uma grande área delimitada por linhas cinzas contendo apenas o escrito "Texto de Node...". Abaixo dela, à esquerda, está o botão azul de "Voltar" e, à direita, outro botão em branco com "Excluir documento" escrito em vermelho. Ao lado direito da grande área, está uma lista de "Usuários conectados:" contendo apenas o retângulo com o escrito "Evaldo".

Se abrirmos uma nova janela do navegador, abrirmos na página de login do projeto e inserirmos os dados de "Eduarda" que também já está cadastrada, iremos autenticá-la e acessar a parte de documentos.

Clicando em Node, tanto a janela anterior quanto a nova que abrimos aparecerão com o nome "Eduarda" abaixo de "Evaldo" na lista de "Usuários conectados:".

Se a usuária Eduarda se deslogar, a lista será atualizada com sucesso também.

Para implementarmos essas funcionalidades, aprenderemos a:

Esta última parte será para implementarmos a funcionalidade de pessoas usuárias conectadas em um mesmo documento, cujas informações serão guardadas de forma local.

Os pré-requisitos para acompanhar este curso é ter feito o curso anterior de WebSockets: implemente comunicações em tempo real com Socket.IO e MongoDB neste link, visto que aplicaremos conceitos básicos para avançarmos em Socket.IO.

Também é interessante termos feito o curso de Node.js: criptografia e tokens JWT neste link, já que precisaremos criptografar as senhas para deixá-las protegidas, além de manejarmos os tokens JWT para criar seções e autenticar pessoas usuárias.

Vamos lá?

Cadastrando usuários - Refatorando o projeto

Vamos trabalhar em uma versão aprimorada do AluraDocs solicitada pelas usuárias fictícias Eduarda e Juliana, contendo novas funcionalidades.

Na atividade anterior de "Preparando o ambiente", disponibilizamos essa versão com algumas novas modificações no HTML do projeto, e a abriremos no VSCode.

instalaremos as dependências abrindo o Terminal e escrevendo npm install ou apenas npm i na linha de comando, executando com a tecla "Enter".

Terminada a instalação, já teremos a pasta "node_modules" na aba lateral esquerda do Explorador do VSCode. Em seguida, executaremos npm run dev no Terminal para vermos se o projeto já está rodando no navegador também.

Usamos estes termos no comando porque temos um script com este nome em "scripts": do arquivo package.json. O executamos no Terminal e receberemos a mensagem de que nos conectamos ao banco de dados com sucesso e de que estamos executando o Servidor na porta 3000.

No navegador, digitaremos "localhost:3000" na barra de busca e acessaremos a página do AluraDocs. Conseguiremos ver as outras telas digitando "/login/index.html" ao final do endereço também.

Então tudo deverá estar funcionando e sendo servido pelo Node.js.

De volta ao VSCode, fecharemos o Terminal integrado e abriremos a pasta "public". Dentro dela, organizamos os arquivos HTML que criamos em pastas próprias, como a "documento" que conterá o arquivo index.html que era o antigo documento HTML.

Já os arquivos JavaScript referentes à essa página, o documento.js e socket-front-documento.js, poderão ficar na mesma pasta, deixando tudo mais organizado.

Da mesma forma, fizemos as pastas de "cadastro" e "login" dentro de "public" com a mesma organização de "documento". Ambas possuem somente o index.html porque ainda iremos criar os outros arquivos .js para implementarmos as novas funcionalidades.

Ainda, a página inicial index.html que mostra todos os documentos adicionados pelas pessoas usuárias Eduarda e Juliana está dentro da raiz "public" também.

A segunda diferença que temos em relação ao curso anterior é que, dentro da pasta "servidor", temos uma nova pasta chamada "db" que contém os arquivos relacionados ao banco de dados: dbConnect.js e documentosDb.js. O restante, servidor.js e socket-back.js, continua somente na pasta "servidor".

Essa pasta é a antiga "src", e a renomeamos para que fique mais intuitivo e específico, afinal, como significa "source" ou "fonte" em português, pode ter vários significados dependendo do contexto em que estamos trabalhando.

O nome "servidor" faz mais sentido em nosso projeto porque estamos lidando com front-end e back-end ao mesmo tempo, então é melhor indicarmos que se trata da parte de back-end.

Agora que sabemos as diferenças de pastas e arquivos em relação ao curso anterior, implementaremos uma refatoração.

Abrindo o socket-back.js em "servidor", teremos io.on() contendo "connection" para escutarmos a conexão de cada cliente do Servidor, e estamos fazendo várias tratativas para diversos eventos, como "obter_documentos", "adicionar_documento", "texto_editor" e "excluir_documento".

Porém, se mantivermos tudo em um mesmo arquivo, ficará muito grande conforme adicionamos funcionalidades. O ideal é termos basicamente um arquivo apenas com as específicas de uma página HTML, por exemplo.

Então, as funcionalidades de "obter_documentos" e "adicionar_documento" ficariam separadas em um arquivo relativo à página inicial onde os documentos são exibidos.

Vamos começar!

Dentro da pasta "servidor", criaremos uma nova pasta chamada "registrarEventos". Dentro dela, criaremos um novo arquivo chamado registrarEventosInicio.js.

Copiaremos apenas o nome do arquivo para colarmos na primeira linha e criarmos a função registrarEventosInicio(). Abriremos as chaves e inseriremos todo o código relacionado aos "ouvintes" do evento.

De volta ao socket-back.js, recortaremos com as teclas "Ctrl + X" todo o bloco pertencente às chaves de socket.on() com "obter_documentos" e o de "adicionar_documento", e colaremos com "Ctrl + V" dentro da nova function que criamos.

Porém, no momento em que mudamos o código de lugar, precisaremos receber algumas referências, que neste caso são o socket e o io. Então os passamos como parâmetro de registrarEventosInicio().

Também precisaremos importar as funções que estávamos usando no arquivo anterior, pois usaremos neste. No socket-back.js, copiaremos todo o primeiro bloco de import a partir de "./db/documentosDb.js" e colaremos no início do arquivo registrarEventosInicio.js.

Como não utilizaremos algumas dessas importações, apagaremos as linhas de atualizaDocumento e excluiDocumento. O caminho do import também mudará, ficando "../db/documentosDb.js" com dois pontos finais no começo porque o arquivo atual está dentro da pasta "registrarEventosInicio", e precisaremos subir um nível nas pastas.

import {
  adicionarDocumento,
  encontrarDocumento,
  obterDocumentos,
} from "../db/documentosDb.js";

function registrarEventosInicio() {
  socket.on("obter_documentos", async (devolverDocumentos) => {
    const documentos = await obterDocumentos();

    devolverDocumentos(documentos);
  });

  socket.on("adicionar_documento", async (nome) => {
    const documentoExiste = (await encontrarDocumento(nome)) !== null;

    if (documentoExiste) {
      socket.emit("documento_existente", nome);
    } else {
      const resultado = await adicionarDocumento(nome);

      if (resultado.acknowledged) {
        io.emit("adicionar_documento_interface", nome);
      }
    }
  });
}

Voltaremos ao socket-back.js e apagaremos adicionarDocumento e obterDocumentos, afinal não o usaremos mais neste arquivo.

Em seguida, recortaremos com as teclas "Ctrl + X" todos os blocos contendo os eventos relacionados à página de um documento específico, o "selecionar_documento", "texto_editor" e "excluir_documento".

Dentro da pasta "registrarEventos", criaremos um novo arquivo chamado registrarEventosDocumento.js e inseriremos uma nova function registrarEventosDocumento() que também receberá socket, io.

Dentro da função, colaremos o que acabamos de recortar do socket-back.js. De volta a este, copiaremos com "Ctrl + C" o primeiro bloco de import e colaremos no topo do arquivo novo que acabamos de criar.

Precisaremos fazer a exportação das funções dos arquivos que criamos usando. Na última linha de registrarEventosDocumento.js, escreveremos export default de registrarEventosDocumento.

Também atualizaremos o caminho do import para "../db/documentosDb.js" com dois pontos finais no começo.

import {
  atualizaDocumento,
  encontrarDocumento,
  excluirDocumento,
} from "../db/documentosDb.js";

function registrarEventosDocumento(socket, io) {
  socket.on("selecionar_documento", async (nomeDocumento, devolverTexto) => {
    socket.join(nomeDocumento);

    const documento = await encontrarDocumento(nomeDocumento);

    if (documento) {
      devolverTexto(documento.texto);
    }
  });

  socket.on("texto_editor", async ({ texto, nomeDocumento }) => {
    const atualizacao = await atualizaDocumento(nomeDocumento, texto);

    if (atualizacao.modifiedCount) {
      socket.to(nomeDocumento).emit("texto_editor_clientes", texto);
    }
  });

  socket.on("excluir_documento", async (nome) => {
    const resultado = await excluirDocumento(nome);

    if (resultado.deletedCount) {
      io.emit("excluir_documento_sucesso", nome);
    }
  });
}

export default registrarEventosDocumento;

Depois, iremos ao registrarEventosInicio.js e exportaremos registrarEventosInicio ao final do código também.

Salvaremos, retornaremos ao socket-back.js e importaremos essas funções para que as funcionalidades sejam executadas, pois apenas fizemos uma refatoração para separá-las em diferentes arquivos.

Dentro de io.on() contendo "connection", escreveremos registrarEventosInicio(), aceitaremos o autoimport do VSCode e passaremos socket, io como parâmetro.

Na linha seguinte, inseriremos o registrarEventosDocumento() passando socket, io como parâmetros também.

import registrarEventosInicio from "./registrarEventos/inicio.js";
import registrarEventosDocumento from "./registrarEventos/documento.js";
import io from "./servidor.js";

import io from "./servidor.js";

io.on("connection", (socket) => {
  registrarEventosInicio(socket, io);
  registrarEventosDocumento(socket, io);
});

Se salvarmos, iremos receber a mensagem de que conectamos ao banco de dados com sucesso e que o servidor está "escutando" na porta 3000.

De volta à página no navegador, iremos para "localhost:3000" e acessaremos a página com os documentos listados, em que conseguiremos clicar, abrir um documento e até excluir se quisermos.

Portanto, as funcionalidades devem estar funcionando corretamente.

Cadastrando usuários - Enviando dados de cadastro

Vamos começar implementando a parte de cadastro do AluraDocs.

No navegador, abriremos a página de "localhost:3000" e adicionaremos "/cadastro/index.html" em seguida na barra de endereço.

Quando fazemos isso, aparecerá o formulário de "Cadastro" com os campos de "Usuário" e Senha". Ainda não estão funcionando, mas testaremos colocando uma informação qualquer nos inputs e clicando em "Cadastrar".

Somente atualizaremos a página e os campos estarão em branco, então vamos fazer um código JavaScript que pegará esses dados e enviará ao servidor para cadastrarmos a pessoa usuária no banco de dados.

Abrindo o VSCode, acessaremos a pasta "public > cadastro" onde teremos o index.html. Neste arquivo, encontraremos o formulário em <form com o atributo id="form-cadastro">.

Copiaremos essa identificação porque iremos capturar esse formulário em um arquivo JavaScript para pegarmos os dados digitados nos campos de texto.

Dentro da pasta "cadastro", criaremos um novo arquivo chamado cadastro.js. Faremos a importação deste arquivo no HTML. No index.html, iremos à última linha antes do fim do </body> e adicionaremos uma tag <script src="cadastro.js" seguido do atributo type="module"></script>, permitindo que utilizemos os módulos do document script.

<!DOCTYPE html>
<html lang="pt-BR">

//código omitido

  <main class="w-75 mx-auto">
    <hr>
    <h2 class="display-6 mb-3">Cadastro</h2>

    <form id="form-cadastro">

//código omitido

  </main>

//código omitido

  <script src="/socket.io/socket.io.js"></script>
  <script src="cadastro.js" type="module"></script>
</body>

</html>

Salvaremos e voltaremos ao cadastro.js para escrevermos const form igual a document.getElementById() recebendo "form-cadastro".

Em seguida, digitaremos form.addEventListener() recebendo "submit". Adicionaremos um "ouvinte" para o submit do front-end mesmo, então assim que alguém submeter o formulário, conseguiremos executar uma função call-back que será o segundo parâmetro.

Aplicaremos uma arrow function recebendo o evento de submissão. Como primeira linha de código dentro das chaves, teremos evento.preventDefault() para evitarmos que o formulário atualize a página, já que é um comportamento padrão do HTML.

const form = document.getElementById("form-cadastro");

form.addEventListener("submit", (evento) => {
  evento.preventDefault();

});

Para pegarmos os dados digitamos nos campos de "Usuário" e "Senha", voltaremos ao index.html e, dentro do <form>, teremos a tag <input> contendo um id chamado "input-usuario" e, no campo de senha, teremos seu <input> com a identificação "input-senha".

Copiaremos o primeiro id e, para obtermos o valor digitado, voltaremos para cadastro.js, escreveremos const usuario sendo igual a form[] contendo "input-usuario".

Esta é uma forma de acessarmos os inputs dos formulários de front-end, afinal serão como propriedades do objeto form. Sabendo que "input-usuario" é exatamente nosso campo, adicionaremos .value para obtermos exatamente o que foi escrito no campo de texto.

Faremos a mesma coisa para o "input-senha" na linhas eguinte. Por fim, faremos um console.log() de usuario, senha para vermos se está funcionando.

const form = document.getElementById("form-cadastro");

form.addEventListener("submit", (evento) => {
  evento.preventDefault();

  const nome = form["input-usuario"].value;
  const senha = form["input-senha"].value;

  console.log(usuario, senha);
});

Salvaremos e voltaremos ao navegador para atualizá-lo.

Apertando a tecla "F12", abriremos a aba lateral direita do Inspecionador de código e abriremos o "Console". Quando digitarmos algum valor no campo de "Uusuario", como "Evaldo" e "123" em "senha" que já temos cadastrado por exemplo.

Clicando no botão de "Cadastrar", exibiremos a resposta Evaldo 123 no Console do navegador.

De volta ao VSCode, emitiremos esses dados para o back-end. Ao invés de aplicarmos o console.log(), escreveremos a função emitirCadastrarUsuario() passando um objeto com as propreidades { usuario, senha } que ja criamos.

Ainda iremos criá-la em um arquivo separado seguindo a mesma organização que estamos seguindo no curso anterior.

Dentro da pasta "cadastro", criaremos um novo arquivo socket-front-cadastro.js onde teremos a nova const emitirCadastrarUsuario().

Para usarmos o socket, criaremos uma const com este nome sendo igual a io(). Veremos se este io() está sendo disponibilizado, mas só será através de uma tag específica.

Abrindo o index.html de "cadastro" novamente, teremos o <script> com src="/socket.io/socket.io.js". Isso já será suficiente para disponibilizarmos o io() que estamos usando em socket-front-cadastro.js.

Dentro das chaves da nova função que criamos, escreveremos socket.emit() recebendo o evento "cadastrar usuário ". Depois, receberemos osdadosde cadastro como parâmetro deemitirCadastrarUsuario(), que também será o segundo parâmetro de.emit()`.

Por fim, exportaremos com export de { emitirCadastrarUsuario } ao final do arquivo.

const socket = io();

function emitirCadastrarUsuario(dados) {
  socket.emit("cadastrar_usuario", dados);
}

export { emitirCadastrarUsuario };

Salvaremos' e voltaremos ao cadastro.js para importarmos o emitirCadastrarUsuario() no início do arquivo a partir de "./socket-front-cadastro.js".

import { emitirCadastrarUsuario } from "./socket-front-cadastro.js";

const form = document.getElementById("form-cadastro");

form.addEventListener("submit", (evento) => {
  evento.preventDefault();

  const nome = form["input-usuario"].value;
  const senha = form["input-senha"].value;

  emitirCadastrarUsuario({ nome, senha });
});

Para vermos se está funcionando, iremos ao "servidor" e acessaremos a pasta "registrarEventos" onde criaremos um novo arquivo chamado registrarEventosCadastro.js para fazer referência à página de cadastro.

Dentro dele, teremos uma nova função chamada registrarEventosCadastro() recebendo socket, io como parâmetros. Essa é exatamente a organização que estamos seguindo da refatoração da aula passada.

Colocaremos todas as funcionalidades de Socket.IO relacionadas à página de cadastro, sendo a primeira socket.on() contendo "cadastrar_usuario". Como segundo parâmetro, teremos uma função call-back que receberá os dados como parâmetros também, e depois faremos um console.log() de dados para atestarmos se as informações estão chegando no servidor usadas no front-end.

Ao final do arquivo, faremos um export default de registrarEventosCadastro.

function registrarEventosCadastro(socket, io) {
  socket.on("cadastrar_usuario", (dados) => {
    console.log(dados);
  });
}

export default registrarEventosCadastro;

Salvaremos e abriremos o arquivo socket-back.js onde importaremos a nova função e a adicionaremos nas chaves de io.on().

Dentro dos parênteses de registrarEventosCadastro(), passaremos socket.io como parâmetros.

import registrarEventosDocumento from "./registrarEventos/registrarEventosDocumento.js";
import registrarEventosInicio from "./registrarEventos/registrarEventosInicio.js";
import registrarEventosCadastro from "./registrarEventos/registrarEventosCadastro.js";

import io from "./servidor.js";

io.on("connection", (socket) => {
  registrarEventosInicio(socket, io);
  registrarEventosDocumento(socket, io);
  registrarEventosCadastro(socket, io);
});

Feito isso, salvaremos e veremos se os dados estão trafegando com sucesso.

De volta à página atualizada no navegador, escreveremos "Juliana" no campo de "Usuario" passando a senha "123". Apertaremos "Enter" ou o botão de "Cadastrar" para enviarmos.

Voltaremos ao VSCode com o Terminal aberto e veremos que há um objeto criado com a propriedade usuario: e senha: contendo os valores que adicionamos nos campos de texto.

A passagem de dados de front-end para back-end já estarão funcionando.

Para finalizarmos, mudaremos o nomes dos arquivos de "registrarEventos" porque os caminhos das importações estão muito grandes, e é interessante reduzi-los.

Clicaremos em registrarEventosCadastro.js e apertaremos a tecla "F2" para renomearmos para cadastro.js apenas. No momento em que renomeamos o arquivo, o VSCode nos mostra uma caixa perguntando se queremos atualizar as importações desses arquivos.

Clicaremos em "Sim" para fazermos a alteração automaticamente.

Faremos a mesma coisa para os outros dois arquivos, em que registrarEventosDocumento.js será apenas documento.js e registrarEventosInicio.js para apenas inicio.js, aceitando as alterações automáticas nos demais arquivos.

import registrarEventosDocumento from "./registrarEventos/documento.js";
import registrarEventosInicio from "./registrarEventos/inicio.js";
import registrarEventosCadastro from "./registrarEventos/cadastro.js";

//código omitido

Com isso, salvaremos o arquivo socket-back.js com os caminhos das importações atualizadas e abriremos o Terminal integrado para vermos que a aplicação está funcionando normalmente.

Abrindo a página no navegador, atualizaremos o formulário e digitaremos "Juliana" com a senha "123" para cadastrarmos. Clicando no botão e abrindo o Terminal do VSCode novamente, veremos que aparecerá os valores que inserimos.

A seguir, pegaremos esses dados e começaremos a manipular o banco de dados para efetivamente criarmos as pessoas usuárias do AluraDocs.

Sobre o curso WebSockets: implemente autenticação e avance no Socket.IO

O curso WebSockets: implemente autenticação e avance no Socket.IO possui 193 minutos de vídeos, em um total de 48 atividades. Gostou? Conheça nossos outros cursos de Node.JS em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Node.JS acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri, a inteligência artificial da Alura

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas