Project Templates
Social Network
Sistema de Autenticação para Sua Rede Social
54 min
introdução neste tutorial, você aprenderá como implementar um sistema de autenticação abrangente para sua aplicação web de rede social usando o back4app como seu serviço de backend você construirá funcionalidades para registro de usuários, login, recuperação de senha e gerenciamento de sessão recursos críticos para qualquer aplicação social moderna back4app é uma plataforma backend as a service (baas) construída sobre o parse server que permite aos desenvolvedores criar aplicações escaláveis sem gerenciar a infraestrutura do servidor suas capacidades de autenticação de usuários integradas o tornam perfeito para implementar rapidamente sistemas de gerenciamento de usuários seguros ao final deste tutorial, você terá criado um sistema de autenticação totalmente funcional semelhante ao utilizado no back4gram, uma aplicação de rede social você implementará registro de usuários com validação, login seguro, recuperação de senha e sessões persistentes em toda a aplicação, proporcionando aos seus usuários uma experiência contínua enquanto mantém suas contas seguras projeto back4gram encontre aqui o código completo para um projeto de exemplo de rede social construído com back4app pré requisitos para completar este tutorial, você precisará uma conta back4app você pode se inscrever para uma conta gratuita em back4app com https //www back4app com um projeto back4app configurado você pode aprender como criar um novo projeto seguindo nosso guia de introdução ao back4app https //www back4app com/docs/get started/welcome node js instalado em sua máquina local conhecimento básico de javascript, react js e conceitos de api restful familiaridade com conceitos modernos de desenvolvimento web (componentes, gerenciamento de estado, etc ) passo 1 – entendendo o sistema de gerenciamento de usuários do back4app antes de mergulhar no código, é importante entender como o back4app lida com o gerenciamento de usuários o back4app é construído sobre o parse server, que fornece uma classe parse user projetada especificamente para autenticação a classe parse user a classe parse user no back4app estende o objeto padrão parse com funcionalidades especializadas para autenticação de usuários inclui vários campos embutidos nome de usuário um identificador único para o usuário (obrigatório) senha a senha do usuário (obrigatória para cadastro, mas não armazenada em forma recuperável) email o endereço de email do usuário (opcional, mas recomendado) emailverificado um booleano indicando se o usuário verificou seu email dadosdeautenticação dados de autenticação para autenticação de terceiros você também pode adicionar campos personalizados para armazenar informações adicionais do usuário, como fotos de perfil, biografias ou quaisquer outros dados específicos do usuário gerenciamento de sessão quando um usuário faz login, o back4app cria um token de sessão que identifica a sessão do usuário este token é usado para autenticar solicitações subsequentes sem exigir que o usuário faça login novamente o token de sessão é gerenciado automaticamente pelo sdk do parse, mas também pode ser controlado manualmente, se necessário veja como funciona o fluxo da sessão o usuário fornece credenciais (nome de usuário/e mail e senha) back4app valida as credenciais se válidas, o back4app cria um token de sessão o token é armazenado localmente (tipicamente em localstorage ou um mecanismo similar) o token é incluído em solicitações de api subsequentes para autenticar o usuário vamos ver como isso é implementado no aplicativo back4gram o código de inicialização do parse geralmente se parece com isto // initialize parse with your back4app credentials parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com/"; essa configuração no aplicativo back4gram permite que todos os componentes acessem o sdk do parse e façam solicitações autenticadas uma vez que um usuário faça login recursos de segurança o back4app fornece vários recursos de segurança para gerenciamento de usuários armazenamento seguro de senhas as senhas nunca são armazenadas em texto simples, mas são automaticamente hashadas e salgadas gerenciamento de sessões as sessões de usuário podem ser gerenciadas e revogadas através do painel do back4app listas de controle de acesso (acls) você pode controlar quem pode ler ou escrever objetos específicos verificação de email o back4app pode enviar emails de verificação para os usuários redefinição de senha funcionalidade embutida para redefinições de senha seguras agora que entendemos o básico, vamos passar para a configuração do nosso projeto projeto back4gram encontre aqui o código completo para um projeto de amostra de rede social construído com o back4app passo 2 – configurando seu projeto para demonstrar como implementar a autenticação com o back4app, criaremos uma versão simplificada do aplicativo de rede social back4gram criando uma nova aplicação react primeiro, vamos criar uma nova aplicação react abra seu terminal e execute npx create react app social network auth cd social network auth instalando pacotes necessários em seguida, vamos instalar os pacotes necessários npm install parse react router dom @chakra ui/react @emotion/react @emotion/styled framer motion esses pacotes fornecem parse o sdk javascript para back4app react router dom para roteamento de páginas @chakra ui/react uma biblioteca de componentes para construir a ui estrutura do projeto vamos configurar uma estrutura básica de arquivos para nosso sistema de autenticação src/ ├── components/ │ └── ui/ │ ├── field js │ └── toaster js ├── pages/ │ ├── signuppage js │ ├── loginpage js │ ├── resetpasswordpage js │ ├── profilepage js │ └── feedpage js ├── app js └── index js src/ ├── components/ │ └── ui/ │ ├── field js │ └── toaster js ├── pages/ │ ├── signuppage js │ ├── loginpage js │ ├── resetpasswordpage js │ ├── profilepage js │ └── feedpage js ├── app js └── index js src/ ├── components/ │ └── ui/ │ ├── field js │ └── toaster js ├── pages/ │ ├── signuppage js │ ├── loginpage js │ ├── resetpasswordpage js │ ├── profilepage js │ └── feedpage js ├── app js └── index js configurando o parse sdk agora, vamos inicializar o parse em nossa aplicação crie um arquivo chamado src/parseconfig js import parse from 'parse/dist/parse min js'; // initialize parse parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com/"; export default parse; substitua your app id e your javascript key pelas credenciais do seu projeto back4app você pode encontrá las no seu painel do back4app em configurações do app > segurança e chaves em seguida, vamos atualizar src/index js para importar nossa configuração do parse import react from 'react'; import reactdom from 'react dom/client'; import ' /index css'; import app from ' /app'; import ' /parseconfig'; const root = reactdom createroot(document getelementbyid('root')); root render( \<react strictmode> \<app /> \</react strictmode> ); configurando rotas agora, vamos configurar a estrutura básica de rotas em src/app js import react from 'react'; import { browserrouter as router, routes, route } from 'react router dom'; import {provider} from " /components/ui/provider"; // import pages import signuppage from ' /pages/signuppage'; import loginpage from ' /pages/loginpage'; import resetpasswordpage from ' /pages/resetpasswordpage'; import profilepage from ' /pages/profilepage'; import feedpage from ' /pages/feedpage'; function app() { return ( \<provider> \<router> \<routes> \<route path="/signup" element={\<signuppage />} /> \<route path="/login" element={\<loginpage />} /> \<route path="/reset password" element={\<resetpasswordpage />} /> \<route path="/profile" element={\<profilepage />} /> \<route path="/feed" element={\<feedpage />} /> \<route path="/" element={\<loginpage />} /> \</routes> \</router> \</provider> ); } export default app; criando componentes de ui antes de começarmos a construir as páginas de autenticação, vamos criar alguns componentes de ui reutilizáveis primeiro, vamos criar src/components/ui/toaster js // a simple toast notification system export const toaster = { create ({ title, description, type }) => { alert(`${title} ${description}`); // in a real app, you would use chakra ui's toast system } }; então, crie src/components/ui/field js import react from 'react'; import { formcontrol, formlabel, formerrormessage, formhelpertext } from '@chakra ui/react'; export const field = ({ label, children, errortext, helpertext, rest }) => { return ( \<formcontrol isinvalid={!!errortext} { rest}> {label && \<formlabel>{label}\</formlabel>} {children} {errortext ? ( \<formerrormessage>{errortext}\</formerrormessage> ) helpertext ? ( \<formhelpertext>{helpertext}\</formhelpertext> ) null} \</formcontrol> ); }; agora estamos prontos para implementar nosso sistema de autenticação! projeto back4gram encontre aqui o código completo para um projeto de exemplo de rede social construído com back4app passo 3 – criando um sistema de registro de usuário vamos começar implementando a página de cadastro esta página permitirá que novos usuários criem uma conta fornecendo um nome de usuário, e mail e senha crie um arquivo chamado src/pages/signuppage js import react, { usestate } from 'react'; import { usenavigate, link as routerlink } from 'react router dom'; import { box, button, heading, input, vstack, link, text, flex } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function signuppage() { const \[username, setusername] = usestate(''); const \[email, setemail] = usestate(''); const \[password, setpassword] = usestate(''); const \[confirmpassword, setconfirmpassword] = usestate(''); const \[isloading, setisloading] = usestate(false); const \[showpassword, setshowpassword] = usestate(false); const \[errors, seterrors] = usestate({}); const navigate = usenavigate(); const validateform = () => { const newerrors = {}; if (!username trim()) { newerrors username = 'username is required'; } if (!email trim()) { newerrors email = 'email is required'; } else if (!/\s+@\s+\\ \s+/ test(email)) { newerrors email = 'email is invalid'; } if (!password) { newerrors password = 'password is required'; } else if (password length < 6) { newerrors password = 'password must be at least 6 characters'; } if (password !== confirmpassword) { newerrors confirmpassword = 'passwords do not match'; } seterrors(newerrors); return object keys(newerrors) length === 0; }; const handlesignup = async (e) => { e preventdefault(); if (!validateform()) { return; } setisloading(true); try { // create a new user using parse const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); toaster create({ title 'success', description 'account created successfully!', type 'success', }); navigate('/feed'); } catch (error) { console error('error signing up ', error); toaster create({ title 'error', description error message, type 'error', }); } finally { setisloading(false); } }; return ( \<box maxw="400px" mx="auto" p={4}> \<vstack spacing={6} align="stretch"> \<heading textalign="center">create an account\</heading> \<form onsubmit={handlesignup}> \<vstack spacing={4} align="stretch"> \<field isinvalid={!!errors username}> \<field label>username\</field label> \<input type="text" value={username} onchange={(e) => setusername(e target value)} /> {errors username && ( \<field errortext>{errors username}\</field errortext> )} \</field> \<field isinvalid={!!errors email}> \<field label>email\</field label> \<input type="email" value={email} onchange={(e) => setemail(e target value)} /> {errors email && ( \<field errortext>{errors email}\</field errortext> )} \</field> \<field isinvalid={!!errors password}> \<field label>password\</field label> \<flex position="relative"> \<input type={showpassword ? 'text' 'password'} value={password} onchange={(e) => setpassword(e target value)} /> \<button aria label={showpassword ? 'hide password' 'show password'} size="xs" position="absolute" right="0 25rem" top="50%" transform="translatey( 50%)" onclick={() => setshowpassword(!showpassword)} zindex={2} \> {showpassword ? 'hide' 'show'} \</button> \</flex> {errors password && ( \<field errortext>{errors password}\</field errortext> )} \</field> \<field isinvalid={!!errors confirmpassword}> \<field label>confirm password\</field label> \<input type={showpassword ? 'text' 'password'} value={confirmpassword} onchange={(e) => setconfirmpassword(e target value)} /> {errors confirmpassword && ( \<field errortext>{errors confirmpassword}\</field errortext> )} \</field> \<button type="submit" colorscheme="blue" isloading={isloading} mt={2} \> sign up \</button> \</vstack> \</form> \<text textalign="center"> already have an account?{' '} \<link as={routerlink} to="/login" color="blue 400"> log in \</link> \</text> \</vstack> \</box> ); } export default signuppage; este código cria um formulário de inscrição com os seguintes recursos validação de formulário verifica se todos os campos obrigatórios estão preenchidos corretamente antes do envio alternância de visibilidade da senha permite que os usuários vejam o que estão digitando tratamento de erros exibe mensagens de erro apropriadas para falhas de validação e inscrição estado de carregamento mostra um indicador de carregamento durante o processo de inscrição entendendo o processo de cadastro de usuários do back4app a parte chave deste código é a handlesignup função, que usa a classe parse user do back4app para criar um novo usuário const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); quando você chama signup() , o back4app valida os dados fornecidos hash a senha de forma segura cria um novo usuário no banco de dados cria e retorna um token de sessão o token de sessão é armazenado automaticamente pelo sdk do parse após um cadastro bem sucedido, o usuário é automaticamente logado, então podemos redirecioná lo diretamente para a página de feed no aplicativo back4gram, isso é implementado de forma semelhante em signuppage js a principal diferença é que a implementação do back4gram usa componentes de ui mais avançados e pode incluir campos adicionais ou lógica de validação com a funcionalidade de cadastro completa, vamos passar para a implementação da funcionalidade de login projeto back4gram encontre aqui o código completo para um projeto de amostra de rede social construído com o back4app passo 4 – implementando o login do usuário agora, vamos criar a página de login que permitirá aos usuários se autenticarem com suas credenciais crie um arquivo chamado src/pages/loginpage js import react, { usestate, useeffect } from 'react'; import { usenavigate, link as routerlink } from 'react router dom'; import { box, heading, input, button, text, vstack, link, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function loginpage() { const \[username, setusername] = usestate(''); const \[password, setpassword] = usestate(''); const \[isloading, setisloading] = usestate(false); const \[error, seterror] = usestate(''); const \[currentuser, setcurrentuser] = usestate(null); const navigate = usenavigate(); // check if a user is already logged in useeffect(() => { const checkcurrentuser = async () => { try { const user = await parse user current(); if (user) { setcurrentuser(user); navigate('/feed'); } } catch (error) { console error('error checking current user ', error); } }; checkcurrentuser(); }, \[navigate]); const handlelogin = async (e) => { e preventdefault(); if (!username || !password) { seterror('username and password are required'); return; } setisloading(true); try { // login with parse const loggedinuser = await parse user login(username, password); toaster create({ title 'login successful!', description `welcome back, ${loggedinuser getusername()}!`, type 'success', }); // redirect to feed after successful login navigate('/feed'); } catch (error) { toaster create({ title 'login failed', description error message, type 'error', }); seterror(error message); } finally { setisloading(false); } }; return ( \<box maxw="md" mx="auto" p={8} border="1px solid" bordercolor="gray 600" borderradius="md"> \<heading as="h1" size="xl" mb={6} textalign="center"> social network login \</heading> \<form onsubmit={handlelogin}> \<vstack spacing={4}> \<field label="username"> \<input type="text" value={username} onchange={(e) => setusername(e target value)} placeholder="your username" required /> \</field> \<field label="password" errortext={error} \> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="your password" required /> \</field> \<link as={routerlink} to="/reset password" alignself="flex end" fontsize="sm"> forgot password? \</link> \<button colorscheme="blue" width="full" type="submit" isloading={isloading} \> log in \</button> \</vstack> \</form> \<text textalign="center" mt={6}> don't have an account?{' '} \<link as={routerlink} to="/signup" color="blue 500"> sign up \</link> \</text> \</box> ); } export default loginpage; esta página de login tem as seguintes características redirecionamento automático se um usuário já estiver logado, ele é redirecionado automaticamente para a página de feed validação de formulário garante que o nome de usuário e a senha sejam fornecidos antes da submissão tratamento de erros exibe mensagens de erro apropriadas para tentativas de login falhadas estado de carregamento mostra um indicador de carregamento durante o processo de login link para redefinição de senha fornece um link para a página de redefinição de senha entendendo o processo de login do back4app as partes principais deste código são verificando se há um usuário logado existente usando parse user current() fazendo login de um usuário com parse user login(username, password) quando um usuário faz login com back4app as credenciais são enviadas ao servidor para validação se válidas, um token de sessão é gerado e retornado o sdk do parse armazena automaticamente esse token o objeto do usuário é retornado com os dados do usuário atual o token de sessão armazenado é então usado automaticamente pelo sdk do parse para todas as solicitações subsequentes, permitindo que o usuário permaneça logado no aplicativo back4gram, o sistema de login é implementado de forma semelhante em loginpage js , mas com componentes de ui mais avançados e potencialmente recursos adicionais, como opções de login social agora vamos passar para a implementação da funcionalidade de redefinição de senha projeto back4gram encontre aqui o código completo para um projeto de amostra de rede social construído com back4app passo 5 – funcionalidade de redefinição de senha em seguida, vamos criar a página de redefinição de senha que permitirá aos usuários recuperar suas contas se esquecerem suas senhas crie um arquivo chamado src/pages/resetpasswordpage js import react, { usestate } from 'react'; import { link as routerlink } from 'react router dom'; import { box, heading, input, button, text, vstack, link, alert, alerticon, alerttitle, alertdescription, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function resetpasswordpage() { const \[email, setemail] = usestate(''); const \[isloading, setisloading] = usestate(false); const \[error, seterror] = usestate(''); const \[issuccess, setissuccess] = usestate(false); const handleresetpassword = async (e) => { e preventdefault(); if (!email) { seterror('email is required'); return; } // basic email validation const emailregex = /^\[^\s@]+@\[^\s@]+\\ \[^\s@]+$/; if (!emailregex test(email)) { seterror('invalid email format'); return; } setisloading(true); seterror(''); try { // request password reset await parse user requestpasswordreset(email); setissuccess(true); toaster create({ title 'email sent', description 'check your inbox for password reset instructions ', type 'success', }); } catch (error) { toaster create({ title 'reset request failed', description error message, type 'error', }); seterror(error message); } finally { setisloading(false); } }; return ( \<box maxw="md" mx="auto" p={8} border="1px solid" bordercolor="gray 600" borderradius="md"> \<heading as="h1" size="xl" mb={6} textalign="center"> reset password \</heading> {issuccess ? ( \<alert status="success" borderradius="md"> \<alerticon /> \<box> \<alerttitle>email sent successfully!\</alerttitle> \<alertdescription> check your inbox for password reset instructions \</alertdescription> \</box> \</alert> ) ( \<form onsubmit={handleresetpassword}> \<vstack spacing={4}> \<text> enter your email and we'll send you instructions to reset your password \</text> \<field label="email" errortext={error} \> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="your email address" required /> \</field> \<button colorscheme="blue" width="full" type="submit" isloading={isloading} \> send instructions \</button> \<link as={routerlink} to="/login" color="blue 500"> back to login \</link> \</vstack> \</form> )} \</box> ); } export default resetpasswordpage; esta página de redefinição de senha inclui validação de email garante que um formato de email válido seja fornecido estado de sucesso mostra uma mensagem de sucesso após o envio do email de redefinição tratamento de erros exibe mensagens de erro apropriadas se a solicitação de redefinição falhar estado de carregamento mostra um indicador de carregamento durante o processo de solicitação de redefinição entendendo o processo de redefinição de senha do back4app a parte chave deste código é usar o parse user requestpasswordreset(email) método do back4app para enviar um email de redefinição de senha ao usuário quando um usuário solicita uma redefinição de senha com o back4app o back4app verifica se o email existe no banco de dados se o email for encontrado, um email de redefinição é enviado ao usuário o email contém um link com um token seguro quando o usuário clica no link, ele é direcionado para uma página de redefinição de senha após definir uma nova senha, ele pode fazer login com suas novas credenciais no aplicativo back4gram, a funcionalidade de redefinição de senha é implementada de forma semelhante em resetpasswordpage js , usando os mesmos métodos da api do back4app, mas potencialmente com componentes de ui mais avançados ou recursos adicionais agora que implementamos os recursos principais de autenticação, vamos nos concentrar na gestão de sessões projeto back4gram encontre aqui o código completo para um projeto de amostra de rede social construído com back4app passo 6 – gestão de sessões e persistência um dos aspectos chave de qualquer sistema de autenticação é a gestão adequada de sessões isso garante que os usuários permaneçam logados enquanto navegam pelo seu aplicativo e que suas sessões sejam seguras vamos criar uma versão simplificada da página de feed para demonstrar a verificação e gestão de sessões crie um arquivo chamado src/pages/feedpage js import react, { usestate, useeffect } from 'react'; import { usenavigate } from 'react router dom'; import { box, heading, button, text, vstack, hstack, spinner, center, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; function feedpage() { const \[isloading, setisloading] = usestate(true); const \[currentuser, setcurrentuser] = usestate(null); const navigate = usenavigate(); // check if user is authenticated useeffect(() => { const checkauth = async () => { try { console log('checking authentication '); const user = await parse user current(); if (!user) { console log('no user found, redirecting to login'); navigate('/login'); return; } console log('user authenticated ', user id, user get('username')); setcurrentuser(user); setisloading(false); } catch (error) { console error('error checking authentication ', error); navigate('/login'); } }; checkauth(); }, \[navigate]); // function to handle logout const handlelogout = async () => { try { await parse user logout(); navigate('/login'); } catch (error) { console error('error logging out ', error); toaster create({ title 'error', description 'failed to log out please try again ', type 'error', }); } }; if (isloading) { return ( \<center h="100vh"> \<spinner size="xl" /> \</center> ); } return ( \<box maxw="800px" mx="auto" p={8}> \<hstack justify="space between" mb={8}> \<heading>social network feed\</heading> \<hstack> \<text>welcome, {currentuser get('username')}\</text> \<button onclick={handlelogout} colorscheme="red" variant="outline"> log out \</button> \</hstack> \</hstack> \<vstack align="stretch" spacing={4}> \<box p={4} borderwidth={1} borderradius="md"> \<text>this is your feed when authenticated with back4app, you'll see content here \</text> \<text mt={2}>your user id {currentuser id}\</text> \<text>your email {currentuser get('email')}\</text> \</box> \</vstack> \</box> ); } export default feedpage; esta página de feed implementa verificação de autenticação verifica se o usuário está logado antes de mostrar o conteúdo redirecionamento automático redireciona para a página de login se nenhuma sessão de usuário for encontrada funcionalidade de logout permite que o usuário faça logout e limpe sua sessão exibição de informações do usuário mostra informações sobre o usuário atualmente logado entendendo a gestão de sessões do back4app o back4app gerencia sessões de várias maneiras armazenamento automático de sessão o sdk parse armazena automaticamente o token de sessão após o login acesso ao usuário atual você pode acessar o usuário atual com parse user current() expiração da sessão as sessões normalmente expiram após um período definido (configurável no back4app) logout você pode encerrar uma sessão com parse user logout() em uma aplicação de produção como o back4gram, o gerenciamento de sessões é frequentemente mais complexo no arquivo messagespage js do back4gram, podemos ver como a autenticação é verificada no início do componente useeffect(() => { const checkauth = async () => { try { console log('checking authentication '); const user = await parse user current(); if (!user) { console log('no user found, redirecting to login'); navigate('/login'); return; } console log('user authenticated ', user id, user get('username')); setcurrentuser(user); fetchconversations(user); } catch (error) { console error('error checking authentication ', error); navigate('/login'); } }; checkauth(); // clean up subscriptions when component unmounts // }, \[navigate]); esse padrão de verificação de autenticação no nível do componente é comum em aplicações react que usam o back4app considerações de segurança da sessão ao implementar o gerenciamento de sessão com o back4app, considere estas práticas de segurança invalidação automática de sessão configure o back4app para invalidar sessões após um certo período de inatividade armazenamento seguro garanta que os tokens de sessão sejam armazenados de forma segura (o sdk do parse lida com isso automaticamente) apenas https sempre use https para evitar a interceptação de tokens de sessão logout em ações sensíveis exija reautenticação para operações sensíveis, como a alteração de senhas vamos agora ver como implementar o gerenciamento de perfil para completar nosso sistema de autenticação projeto back4gram encontre aqui o código completo para um projeto de amostra de rede social construído com o back4app passo 7 – adicionando gerenciamento de perfil de usuário a peça final do nosso sistema de autenticação é o gerenciamento de perfil do usuário isso permite que os usuários visualizem e atualizem suas informações de perfil crie um arquivo chamado src/pages/profilepage js import react, { usestate, useeffect } from 'react'; import { usenavigate } from 'react router dom'; import { box, button, heading, text, vstack, hstack, input, textarea, avatar, formcontrol, formlabel, spinner, center, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function profilepage() { const \[user, setuser] = usestate(null); const \[username, setusername] = usestate(''); const \[email, setemail] = usestate(''); const \[bio, setbio] = usestate(''); const \[isloading, setisloading] = usestate(true); const \[isupdating, setisupdating] = usestate(false); const \[selectedfile, setselectedfile] = usestate(null); const \[avatarurl, setavatarurl] = usestate(null); const navigate = usenavigate(); // fetch user data useeffect(() => { const fetchuserdata = async () => { try { const currentuser = await parse user current(); if (!currentuser) { navigate('/login'); return; } setuser(currentuser); setusername(currentuser get('username') || ''); setemail(currentuser get('email') || ''); setbio(currentuser get('bio') || ''); // get avatar if available const avatar = currentuser get('avatar'); if (avatar) { setavatarurl(avatar url()); } setisloading(false); } catch (error) { console error('error fetching user data ', error); toaster create({ title 'error', description 'failed to load profile data', type 'error', }); navigate('/login'); } }; fetchuserdata(); }, \[navigate]); // handle profile update const handleupdateprofile = async (e) => { e preventdefault(); setisupdating(true); try { if (!user) return; user set('username', username); user set('email', email); user set('bio', bio); // handle avatar upload if a file is selected if (selectedfile) { const parsefile = new parse file(selectedfile name, selectedfile); await parsefile save(); user set('avatar', parsefile); setavatarurl(parsefile url()); } await user save(); toaster create({ title 'success', description 'profile updated successfully', type 'success', }); } catch (error) { console error('error updating profile ', error); toaster create({ title 'error', description error message, type 'error', }); } finally { setisupdating(false); } }; // handle avatar selection const handlefilechange = (e) => { if (e target files && e target files\[0]) { setselectedfile(e target files\[0]); // create a preview url const previewurl = url createobjecturl(e target files\[0]); setavatarurl(previewurl); } }; // handle logout const handlelogout = async () => { try { await parse user logout(); navigate('/login'); } catch (error) { console error('error logging out ', error); } }; if (isloading) { return ( \<center h="100vh"> \<spinner size="xl" /> \</center> ); } return ( \<box maxw="800px" mx="auto" p={8}> \<hstack justify="space between" mb={8}> \<heading>your profile\</heading> \<button onclick={handlelogout} colorscheme="red" variant="outline"> log out \</button> \</hstack> \<box p={8} borderwidth={1} borderradius="md"> \<form onsubmit={handleupdateprofile}> \<vstack spacing={6} align="start"> \<hstack spacing={8} w="full" align="start"> \<vstack align="center" minw="150px"> \<avatar size="2xl" src={avatarurl} name={username} mb={4} /> \<formcontrol> \<formlabel htmlfor="avatar upload" cursor="pointer" textalign="center"> \<button as="span" size="sm"> change avatar \</button> \<input id="avatar upload" type="file" accept="image/ " onchange={handlefilechange} display="none" /> \</formlabel> \</formcontrol> \</vstack> \<vstack spacing={4} flex="1"> \<field label="username" w="full"> \<input value={username} onchange={(e) => setusername(e target value)} /> \</field> \<field label="email" w="full"> \<input type="email" value={email} onchange={(e) => setemail(e target value)} /> \</field> \<field label="bio" w="full"> \<textarea value={bio} onchange={(e) => setbio(e target value)} placeholder="tell us about yourself" rows={4} /> \</field> \</vstack> \</hstack> \<button type="submit" colorscheme="blue" isloading={isupdating} alignself="flex end" \> save changes \</button> \</vstack> \</form> \</box> \</box> ); } export default profilepage; this profile page provides users with the ability to 1\ view profile information see their username, email, and bio 2\ update profile details change their username, email, and bio 3\ upload a profile picture select and upload a profile image 4\ log out end their session and return to the login page \### understanding back4app's user data management let's examine the key aspects of how back4app handles user data management \#### file uploads with parse file one powerful feature of back4app is the ability to easily handle file uploads using `parse file` ```javascript if (selectedfile) { const parsefile = new parse file(selectedfile name, selectedfile); await parsefile save(); user set('avatar', parsefile); setavatarurl(parsefile url()); } quando você cria um novo parse file , back4app recebe seu arquivo (imagem, documento, etc ) faz o upload para um armazenamento seguro retorna uma referência que pode ser armazenada com seu objeto de usuário torna o arquivo acessível via uma url adicionando campos personalizados de usuário a classe parse user do back4app pode ser estendida com campos personalizados além dos padrões no nosso exemplo, adicionamos bio um campo de texto para descrições de usuários avatar um campo de arquivo para fotos de perfil você pode adicionar quaisquer campos personalizados que precisar para os perfis de usuário do seu aplicativo user set('bio', bio); no aplicativo back4gram, o profilepage js implementa funcionalidade semelhante, mas com mais recursos e uma interface de usuário mais complexa inclui campos adicionais como contagem de seguidores, estatísticas de postagens e um manuseio de imagens mais robusto projeto back4gram encontre aqui o código completo para um projeto de exemplo de rede social construído com back4app passo 8 – testando e protegendo seu sistema de autenticação agora que construímos nosso sistema de autenticação, vamos discutir como testá lo e protegê lo adequadamente testando fluxos de autenticação ao testar seu sistema de autenticação, você deve verificar cada um desses fluxos registro de usuário teste se os usuários podem criar contas com credenciais válidas validação de entrada verifique se erros apropriados aparecem para entradas inválidas processo de login assegure se de que os usuários possam fazer login com credenciais corretas login falhado verifique se erros apropriados aparecem para credenciais incorretas redefinição de senha confirme se o fluxo de redefinição de senha funciona de ponta a ponta persistência de sessão verifique se os usuários permanecem logados entre visitas às páginas processo de logout assegure se de que os usuários possam sair corretamente e que as sessões sejam encerradas vulnerabilidades de segurança comuns a evitar ao construir sistemas de autenticação, esteja ciente desses problemas de segurança comuns armazenamento de senhas nunca armazene senhas em texto simples o back4app cuida disso automaticamente ataques de força bruta implemente limitação de taxa para tentativas de login o back4app fornece essa funcionalidade cross site scripting (xss) limpe as entradas do usuário para evitar injeção de scripts cross site request forgery (csrf) use tokens adequados para verificar a autenticidade da solicitação referências diretas de objetos inseguros não exponha ids ou referências sensíveis em urls melhores práticas de segurança do back4app o back4app fornece várias funcionalidades de segurança que você deve aproveitar 1\ permissões em nível de classe (clps) no seu painel do back4app, você pode definir permissões de nível de classe para controlar quem pode ler, escrever e excluir objetos vá para o seu painel do back4app navegue até banco de dados → navegador clique no botão "segurança" para sua classe de usuário configure as permissões adequadamente \[imagem tela de permissões de nível de classe do back4app mostrando configurações de segurança da classe de usuário] para a classe de usuário, as configurações típicas incluem acesso de leitura público apenas para campos específicos (nome de usuário, avatar) sem acesso público para escrita ou exclusão apenas usuários autenticados podem atualizar seus próprios registros 2\ listas de controle de acesso (acls) para objetos individuais, você pode usar acls para controlar o acesso // set an acl that only allows the current user to read and write this object const useracl = new parse acl(parse user current()); userobject setacl(useracl); await userobject save(); isso garante que apenas o usuário que criou um objeto possa acessá lo ou modificá lo 3\ uso da chave mestra o back4app fornece uma chave mestra que ignora as verificações de segurança nunca exponha isso no código do lado do cliente // never do this in client side code parse cloud usemasterkey(); // this should only be used in cloud code em vez disso, para operações que requerem privilégios elevados, use funções em nuvem 4\ verificação de email ative a verificação de email nas configurações do back4app para garantir que os usuários forneçam endereços de email válidos vá para o seu painel do back4app navegue até configurações do app → configurações de email configure seu adaptador de email ative a verificação de email \[imagem tela de configuração de configurações de email do back4app] 5\ autenticação de dois fatores para segurança adicional, você pode implementar a autenticação de dois fatores usando funções em nuvem do back4app isso requer que os usuários forneçam uma segunda forma de verificação (tipicamente um código enviado para seu telefone ou email) ao fazer login implementando limitação de taxa para proteger contra ataques de força bruta, você pode implementar limitação de taxa usando funções em nuvem // cloud function to handle login with rate limiting parse cloud define("securelogin", async (request) => { const { username, password } = request params; // check for too many failed attempts const query = new parse query("loginattempt"); query equalto("username", username); query greaterthan("createdat", new date(date now() 15 60 1000)); // last 15 minutes const attempts = await query count(); if (attempts >= 5) { throw new error("too many login attempts please try again later "); } try { // attempt to log in const user = await parse user login(username, password); return { success true, user user tojson() }; } catch (error) { // record failed attempt const loginattempt = parse object extend("loginattempt"); const attempt = new loginattempt(); attempt set("username", username); await attempt save(null, { usemasterkey true }); throw error; } }); conclusão neste tutorial, você construiu um sistema de autenticação abrangente para um aplicativo de rede social usando o back4app você implementou recursos de registro de usuário, login, redefinição de senha e gerenciamento de perfil, todos alimentados pelas capacidades de gerenciamento de usuários integradas do back4app vamos recapitular o que você aprendeu sistema de gerenciamento de usuários do back4app você aprendeu como o parse server do back4app fornece autenticação de usuário integrada com a parse user classe registro de usuário você implementou um formulário de inscrição que cria novas contas de usuário no banco de dados do back4app login de usuário você criou um sistema de login que autentica usuários e gerencia sessões redefinição de senha você adicionou um recurso seguro de redefinição de senha que envia e mails de recuperação gerenciamento de sessão você aprendeu como manter sessões de usuário e proteger rotas gerenciamento de perfil você construiu uma página de perfil que permite aos usuários atualizar suas informações e enviar fotos de perfil melhores práticas de segurança você explorou como proteger seu sistema de autenticação usando os recursos de segurança do back4app com o back4app, você pôde se concentrar em criar uma ótima experiência do usuário em vez de construir uma infraestrutura de backend complexa o parse server que alimenta o back4app forneceu todas as apis de autenticação necessárias, garantindo também que os dados dos usuários permanecessem seguros o sistema de autenticação que você construiu forma a base do seu aplicativo de rede social com isso em prática, você pode agora expandir seu aplicativo adicionando recursos como postagens, comentários, curtidas e mensagens diretas, tudo usando o back4app como seu serviço de backend próximos passos integração de login social adicione login com google, facebook ou outros provedores usando as capacidades oauth do back4app segurança aprimorada implemente autenticação de dois fatores para segurança adicional papéis de usuário configure controle de acesso baseado em papéis para diferentes tipos de usuários recursos em tempo real adicione mensagens e notificações em tempo real usando a live query do back4app para o código completo do aplicativo de rede social back4gram, você pode conferir o repositório do github https //github com/templates back4app/back4gram os poderosos serviços de backend do back4app e a integração com o parse server fazem dele uma excelente escolha para construir aplicativos de rede social seguros e escaláveis ao aproveitar suas capacidades de gerenciamento de usuários integradas, você pode criar um sistema de autenticação robusto com esforço mínimo, permitindo que você se concentre em criar recursos únicos que fazem seu aplicativo se destacar