Este artigo o orientará no uso do Strapi CMS com o Next.js para criar um aplicativo onde você pode registrar e autenticar usuários e persistir sessões.

Configurando o aplicativo Next.js

Vamos começar com a configuração do aplicativo Next.js. A maneira mais fácil de configurar isso é usar o pacote create-next-app.

Em seu terminal, execute npx create-next-app next-app, onde next-app é qualquer nome que você preferir para seu projeto.

Isso irá gerar uma pasta chamada next-app. Em seguida, navegue até essa pasta na tela do terminal e execute npm run dev. Você verá o aplicativo em execução na porta localhost 3000.

Configurando o Strapi

Assim como o Next.js, o Strapi também possui um pacote npm que facilita o início de um projeto.

Execute npx create-strapi-app strapi-app para criar um projeto Strapi. Quando solicitado, escolha a opção Quickstart.

Assim que a instalação for concluída, navegue até a pasta strapi-app e execute npm run dev. Ao visitar localhost: 1337, você será solicitado a criar uma conta de administrador. Depois de fazer isso, você deve ser direcionado ao painel de controle do Strapi.

Registrando um usuário no Strapi

Na barra lateral do Strapi em Tipos de coleção , você deve ver Usuários, que é criado por padrão. É aqui que você pode criar usuários manualmente e ver todos os usuários existentes.

Por padrão, a API do Strapi fornece pontos de extremidade para criar, buscar e autenticar usuários.

/auth/local/register é o ponto final para onde precisamos enviar o nome de usuário, e-mail e senha para registrar um usuário.

Para este aplicativo de exemplo, teremos as rotas/register e/profile, onde você pode registrar um usuário e, em seguida, ver o perfil de um usuário, respectivamente. A tela de login estará na página inicial.

Vamos começar com o componente .

Este componente retorna um formulário muito básico, onde o usuário insere seu nome de usuário, e-mail, e senha.

Então, o objeto userData contém essas informações e as envia para o endpoint/api/register, que é algo que criaremos na parte de back-end do aplicativo Next. Observe que para fazer a chamada API, eu uso o pacote axios, então certifique-se de instalá-lo como uma dependência.

npm install–save axios

Assim que a solicitação feita para/api/register for bem-sucedido, roteamos o aplicativo para/profile para exibir as informações do usuário. Criaremos a página/profile mais tarde.

O arquivo a seguir é/components/registerComponent.jsx e o usaremos em/pages/register.jsx:

import {useState} de’reagir’; importar {useRouter} de’próximo/roteador’; importar axios de’axios’; const RegisterComponent=()=> {const router=useRouter (); const [userData, setUserData]=useState ({nome de usuário:”, email:”, senha:”,}) const handleSubmit=async (e)=> {e.preventDefault (); tente {esperar axios.post (‘/api/register’, userData); router.replace (‘/perfil’); } catch (err) {console.log (err.response.data); }} const handleChange=(e)=> {const {nome, valor}=e.target; setUserData ({… userData, [nome]: valor}); } return (

)} exportar RegisterComponent padrão;

Agora crie register.jsx na pasta de páginas e apenas retorne o .

import RegisterComponent de”../components/registerComponent”; const Register=()=> () exportar registro padrão;

A próxima coisa que precisamos fazer é criar o endpoint/api/register.

Em/pages, você encontrará a pasta/api. Nessa pasta, crie register.js. Dessa forma, quando fizermos uma solicitação para/api/register no cliente Next.js, ela será tratada por este arquivo.

import axios from’axios’; importar {setCookie} de’nookies’exportar assíncrono padrão (req, res)=> {const {nome de usuário, senha, e-mail}=req.body; tente {const response=await axios.post (‘http://localhost: 1337/auth/local/register’, {username, email, password,}) setCookie ({res},’jwt’, response.data.jwt , {httpOnly: true, secure: process.env.NODE_ENV!==’development’, maxAge: 30 * 24 * 60 * 60, path:’/’,}); res.status (200).end (); } catch (e) {res.status (400).send (e.response.data.message [0].messages [0]); }}

Conforme mencionado antes, o ponto de extremidade para registrar um usuário é/auth/local/register. Como o Strapi está sendo executado em localhost: 1337, enviamos uma solicitação para http://localhost: 1337/auth/local/register , junto com os dados de nome de usuário, e-mail e senha que recuperamos do corpo da solicitação.

Observe que, se você implantar seu aplicativo Strapi em um servidor remoto, será necessário substituir o URL base de acordo. É uma boa prática armazenar o URL base em uma variável de ambiente e, em seguida, usá-lo em vez de codificar o URL. No entanto, para simplificar, usarei apenas localhost: 1337 em todo este artigo.

A resposta retornada da solicitação POST contém um token JWT. Este token é específico para aquele usuário e deve ser armazenado com segurança para autenticar o usuário automaticamente.

O pacote nookies é uma coleção de funções auxiliares que manipulam cookies em um aplicativo Next.js.

A função setCookie leva o objeto de resposta como o primeiro argumento. O segundo argumento é o nome do cookie e pode ser qualquer coisa que você escolher.

O terceiro argumento é o valor do cookie. Em nosso caso, este é o token JWT retornado da resposta da solicitação e, como último argumento, podemos passar um objeto com opções.

O sinalizador httpOnly impede o cliente-o javascript em execução no navegador-de acessar o cookie para que você possa protegê-lo de possíveis ataques de script entre sites (XSS).

O sinalizador seguro garante que o cookie seja transmitido apenas por uma conexão https segura. Como o host local não é uma conexão https, definimos como false se o ambiente em que estamos executando o aplicativo for de desenvolvimento.

maxAge determina por quantos segundos o cookie será válido. Neste exemplo, é definido como 30 dias.

path determina em qual caminho o cookie deve ser válido. É definido como/para disponibilizar o cookie para todos os caminhos.

Observe que estamos enviando uma mensagem em caso de falha na solicitação. Esta mensagem recuperada de e.response.data.message [0].messages [0] contém informações úteis sobre o motivo da falha da solicitação. Pode ser um e-mail inválido ou um nome de usuário já em uso, etc.

Portanto, essas informações podem ser usadas para mostrar a mensagem de erro apropriada em caso de falha no registro.

Para simplificar, não tratamos essa mensagem de erro no cliente. Simplesmente registramos para mostrar no console do navegador.

Criando a página de perfil do usuário no Strapi

Esta é a rota/profile, onde estão os dados do usuário, como nome de usuário e e-mail , é exibido. Esta rota pode ser visitada diretamente, ou o usuário pode ser roteado para lá quando conectado ou inscrito.

Porque esta página precisa usar o cookie para autenticar o usuário, e porque nós definimos o cookie no lado do servidor com o sinalizador httpsOnly, precisamos ler o cookie no servidor também.

getServerSideProps é uma função Next.js que é executada no servidor em cada solicitação. Nesta função, podemos analisar o cookie para acessar o token JWT e, em seguida, fazer uma solicitação ao Strapi para buscar os dados do usuário. Então, podemos retornar esses dados da função, que os expõe como adereços para a página.

O conteúdo de/pages/profile.jsx é o seguinte:

import {useRouter} from’next/roteador’; importar axios de’axios’; importar recantos de’recantos’; Perfil const=(props)=> {roteador const=useRouter (); const {usuário: {e-mail, nome de usuário}}=props; const logout=async ()=> {try {await axios.get (‘/api/logout’); router.push (‘/’); } catch (e) {console.log (e); }} return (

Nome de usuário: {username}
Email: {email}

)} export const getServerSideProps=async (ctx)=> {const cookies=nookies.get (ctx) let user=null; if (cookies?.jwt) {try {const {data}=await axios.get (‘http://localhost: 1337/users/me’, {headers: {Authorization: `Bearer $ {cookies.jwt}`, },}); usuário=dados; } catch (e) {console.log (e); }} if (! user) {return {redirect: {permanent: false, destination:’/’}}} return {props: {user}}} exportar perfil padrão;

Vamos nos concentrar na função getServerSideProps primeiro. Novamente usamos o pacote nookies para obter os cookies do objeto de contexto (ctx). O nome do cookie que definimos era jwt, daí a verificação da existência de cookies.jwt.

Se este cookie específico estiver lá, enviaremos uma solicitação para o endpoint/users/me do Strapi local servidor com o cabeçalho Authorization contendo o token JWT para buscar as informações do usuário.

Se o cookie não existir ou o token JWT for inválido, a variável do usuário permanecerá nula e redirecionamos a página de volta para/, que é a página inicial com a tela de login. Caso contrário, retornamos o usuário no objeto props, que então se torna disponível como um prop na função de perfil que exportamos.

A função de perfil retorna uma marcação muito básica onde o nome de usuário e o e-mail são exibidos, junto com um log botão-out, que chama a função de logout.

Esta função envia uma solicitação ao endpoint/api/logout para excluir o cookie e, em seguida, rotear a página para/.

Abaixo está/pages/api/logout.js:

import {destroyCookie} from’nookies’export default async (req, res)=> {destroyCookie ({res},’jwt’, {path:’/’,}); res.status (200).end (); }

Efetuando login de usuários

Aqui está o conteúdo de/pages/index.jsx, que é a página inicial e onde o está junto com um botão Registrar, que direciona a página para/registrar a rota.

import {useRouter} de’next/router’; importar axios de’axios’; importar recantos de’recantos’; importar LoginComponent de’../components/loginComponent’; const Home=()=> {const router=useRouter (); const goToRegister=()=> {router.push (‘/registrar’); } return (

)} export const getServerSideProps=async (ctx)=> {const cookies=nookies.get (ctx) let usuário=nulo; if (cookies?.jwt) {try {const {data}=await axios.get (‘http://localhost: 1337/users/me’, {headers: {Authorization: `Bearer $ {cookies.jwt}`, },}); usuário=dados; } catch (e) {console.log (e); }} if (usuário) {return {redirect: {permanent: false, destination:’/profile’}}} return {props: {}}} export default Home;

Como fizemos em/pages/profile.jsx, usamos novamente a função getServerSideProps para buscar o cookie e, em seguida, verificamos a existência do usuário.

Se o usuário existir, então redirecionamos para/rota de perfil. Caso contrário, retornamos um objeto de adereços vazio e permanecemos na mesma rota para renderizar o , que possui o seguinte conteúdo:

import {useState} from’react’; importar {useRouter} de’próximo/roteador’; importar axios de’axios’; const LoginComponent=()=> {const router=useRouter (); const [userData, setUserData]=useState ({identificador:”, senha:”,}); const handleSubmit=async (e)=> {e.preventDefault (); tente {await axios.post (‘/api/login’, {… userData}); router.push (‘/perfil’); } catch (err) {console.log (err.response.data); }} const handleChange=(e)=> {const {nome, valor}=e.target; setUserData ({… userData, [nome]: valor})} return (

)} exportar o LoginComponent padrão;

Este componente renderiza um formulário para obter o e-mail e a senha. Quando o formulário é enviado, uma solicitação POST para/api/login é feita e a página é redirecionada para/profile route.

Abaixo você pode ver o conteúdo de/api/login.js

importar axios de’axios’; importar {setCookie} de’nookies’exportar assíncrono padrão (req, res)=> {const {senha, identificador}=req.body; tente {const postRes=await axios.post (‘http://localhost: 1337/auth/local’, {identifier, password,}) setCookie ({res},’jwt’, postRes.data.jwt, {httpOnly: verdadeiro, seguro: process.env.NODE_ENV!==’development’, maxAge: 30 * 24 * 60 * 60, path:’/’,}); res.status (200).end (); } catch (e) {res.status (400).send (e.response.data.message [0].messages [0]); }}

/auth/local é um endpoint Strapi para fazer o login de um usuário. O objeto enviado para este endpoint deve ter o identificador e as chaves de senha.

Como fizemos em/api/register.js , também definimos um cookie com o mesmo nome e opções para persistir a sessão do usuário.

Conclusão

Neste artigo, demonstramos como usar Next.js como uma pilha completa aplicativo para criar uma interface de usuário com várias rotas e criar endpoints de API para se comunicar com a API do Strapi a fim de registrar e buscar informações do usuário. Definir e buscar cookies no lado do servidor em Next.js também é demonstrado para persistir as sessões de usuário.