Project Templates
Social Network
Sistema de Autenticación para Tu Red Social
54 min
introducción en este tutorial, aprenderás cómo implementar un sistema de autenticación integral para tu aplicación web de red social utilizando back4app como tu servicio backend construirás funcionalidades para el registro de usuarios, inicio de sesión, recuperación de contraseña y gestión de sesiones, características críticas para cualquier aplicación social moderna back4app es una plataforma de backend as a service (baas) construida sobre parse server que permite a los desarrolladores crear aplicaciones escalables sin gestionar la infraestructura del servidor sus capacidades de autenticación de usuarios integradas la hacen perfecta para implementar rápidamente sistemas de gestión de usuarios seguros al final de este tutorial, habrás creado un sistema de autenticación completamente funcional similar al que se utiliza en back4gram, una aplicación de red social implementarás el registro de usuarios con validación, inicio de sesión seguro, recuperación de contraseña y sesiones persistentes a través de la aplicación, brindando a tus usuarios una experiencia fluida mientras mantienes sus cuentas seguras proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app requisitos previos para completar este tutorial, necesitarás una cuenta de back4app puedes registrarte para obtener una cuenta gratuita en back4app com https //www back4app com un proyecto de back4app configurado puedes aprender a crear un nuevo proyecto siguiendo nuestra guía de introducción a back4app https //www back4app com/docs/get started/welcome node js instalado en tu máquina local conocimientos básicos de javascript, react js y conceptos de api restful familiaridad con conceptos modernos de desarrollo web (componentes, gestión de estado, etc ) paso 1 – entendiendo el sistema de gestión de usuarios de back4app antes de sumergirte en el código, es importante entender cómo back4app maneja la gestión de usuarios back4app está construido sobre parse server, que proporciona una parse user clase diseñada específicamente para la autenticación la clase parse user la parse user clase en back4app extiende el objeto estándar de parse con funcionalidad especializada para la autenticación de usuarios incluye varios campos incorporados nombre de usuario un identificador único para el usuario (requerido) contraseña la contraseña del usuario (requerida para el registro pero no almacenada en forma recuperable) correo electrónico la dirección de correo electrónico del usuario (opcional pero recomendado) correoverificado un booleano que indica si el usuario ha verificado su correo electrónico datosdeautenticación datos de autenticación para la autenticación de terceros también puedes agregar campos personalizados para almacenar información adicional del usuario, como fotos de perfil, biografías o cualquier otro dato específico del usuario gestión de sesiones cuando un usuario inicia sesión, back4app crea un token de sesión que identifica la sesión del usuario este token se utiliza para autenticar solicitudes posteriores sin requerir que el usuario inicie sesión nuevamente el token de sesión es gestionado automáticamente por el sdk de parse, pero también puede ser controlado manualmente si es necesario así es como funciona el flujo de sesión el usuario proporciona credenciales (nombre de usuario/correo electrónico y contraseña) back4app valida las credenciales si son válidas, back4app crea un token de sesión el token se almacena localmente (típicamente en localstorage o un mecanismo similar) el token se incluye en las solicitudes api subsiguientes para autenticar al usuario veamos cómo se implementa esto en la aplicación back4gram el código de inicialización de parse típicamente se ve así // initialize parse with your back4app credentials parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com/"; esta configuración en la aplicación back4gram permite que todos los componentes accedan al sdk de parse y realicen solicitudes autenticadas una vez que un usuario inicia sesión características de seguridad back4app proporciona varias características de seguridad para la gestión de usuarios almacenamiento seguro de contraseñas las contraseñas nunca se almacenan en texto plano, sino que se hash y se salan automáticamente gestión de sesiones las sesiones de usuario pueden ser gestionadas y revocadas a través del panel de control de back4app listas de control de acceso (acls) puedes controlar quién puede leer o escribir objetos específicos verificación de correo electrónico back4app puede enviar correos electrónicos de verificación a los usuarios restablecimiento de contraseña funcionalidad integrada para restablecimientos de contraseña seguros ahora que entendemos lo básico, pasemos a configurar nuestro proyecto proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 2 – configurando tu proyecto para demostrar cómo implementar la autenticación con back4app, crearemos una versión simplificada de la aplicación de red social back4gram creando una nueva aplicación react primero, vamos a crear una nueva aplicación react abre tu terminal y ejecuta npx create react app social network auth cd social network auth instalando paquetes requeridos a continuación, instalaremos los paquetes necesarios npm install parse react router dom @chakra ui/react @emotion/react @emotion/styled framer motion estos paquetes proporcionan parse el sdk de javascript para back4app react router dom para el enrutamiento de páginas @chakra ui/react una biblioteca de componentes para construir la interfaz de usuario estructura del proyecto vamos a configurar una estructura de archivos básica para nuestro sistema de autenticación src/ ├── components/ │ └── ui/ │ ├── field js │ └── toaster js ├── pages/ │ ├── signuppage js │ ├── loginpage js │ ├── resetpasswordpage js │ ├── profilepage js │ └── feedpage js ├── app js └── index js configurando parse sdk ahora, inicialicemos parse en nuestra aplicación crea un archivo llamado 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; reemplaza your app id y your javascript key con las credenciales de tu proyecto de back4app puedes encontrarlas en tu panel de back4app bajo configuración de la app > seguridad y claves a continuación, actualicemos src/index js para importar nuestra configuración de 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 rutas ahora, configuremos la estructura básica de enrutamiento en 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; creando componentes de ui antes de comenzar a construir las páginas de autenticación, creemos algunos componentes de ui reutilizables primero, creemos 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 } }; luego, crea 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> ); }; ¡ahora estamos listos para implementar nuestro sistema de autenticación! proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 3 – creando un sistema de registro de usuarios comencemos implementando la página de registro esta página permitirá a los nuevos usuarios crear una cuenta proporcionando un nombre de usuario, correo electrónico y contraseña crea un archivo llamado 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 crea un formulario de registro con las siguientes características validación de formulario verifica que todos los campos obligatorios estén completos correctamente antes de la presentación alternar visibilidad de contraseña permite a los usuarios ver lo que están escribiendo manejo de errores muestra mensajes de error apropiados para fallos de validación y registro estado de carga muestra un indicador de carga durante el proceso de registro entendiendo el proceso de registro de usuarios de back4app la parte clave de este código es la handlesignup función, que utiliza la parse user clase de back4app para crear un nuevo usuario const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); cuando llamas a signup() , back4app valida los datos proporcionados hash segura la contraseña crea un nuevo usuario en la base de datos crea y devuelve un token de sesión el token de sesión se almacena automáticamente por el sdk de parse después de un registro exitoso, el usuario inicia sesión automáticamente, por lo que podemos redirigirlo directamente a la página de inicio en la aplicación back4gram, esto se implementa de manera similar en signuppage js la principal diferencia es que la implementación de back4gram utiliza componentes de ui más avanzados y puede incluir campos adicionales o lógica de validación con la funcionalidad de registro completa, pasemos a implementar la funcionalidad de inicio de sesión proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 4 – implementando el inicio de sesión de usuario ahora, vamos a crear la página de inicio de sesión que permitirá a los usuarios autenticarse con sus credenciales crea un archivo llamado 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 inicio de sesión tiene las siguientes características redirección automática si un usuario ya ha iniciado sesión, se le redirige automáticamente a la página de inicio validación de formulario asegura que se proporcionen el nombre de usuario y la contraseña antes de la presentación manejo de errores muestra mensajes de error apropiados para los intentos de inicio de sesión fallidos estado de carga muestra un indicador de carga durante el proceso de inicio de sesión enlace para restablecer contraseña proporciona un enlace a la página de restablecimiento de contraseña entendiendo el proceso de inicio de sesión de back4app las partes clave de este código son verificando si hay un usuario conectado existente usando parse user current() iniciando sesión de un usuario con parse user login(username, password) cuando un usuario inicia sesión con back4app las credenciales se envían al servidor para validación si son válidas, se genera y devuelve un token de sesión el sdk de parse almacena automáticamente este token el objeto de usuario se devuelve con los datos del usuario actual el token de sesión almacenado se utiliza automáticamente por el sdk de parse para todas las solicitudes posteriores, permitiendo que el usuario permanezca conectado en la aplicación back4gram, el sistema de inicio de sesión se implementa de manera similar en loginpage js , pero con componentes de interfaz de usuario más avanzados y potencialmente características adicionales como opciones de inicio de sesión social ahora pasemos a implementar la funcionalidad de restablecimiento de contraseña proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 5 – funcionalidad de restablecimiento de contraseña a continuación, vamos a crear la página de restablecimiento de contraseña que permitirá a los usuarios recuperar sus cuentas si olvidan sus contraseñas crea un archivo llamado 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 restablecimiento de contraseña incluye validación de correo electrónico asegura que se proporcione un formato de correo electrónico válido estado de éxito muestra un mensaje de éxito después de que se envía el correo electrónico de restablecimiento manejo de errores muestra mensajes de error apropiados si la solicitud de restablecimiento falla estado de carga muestra un indicador de carga durante el proceso de solicitud de restablecimiento entendiendo el proceso de restablecimiento de contraseña de back4app la parte clave de este código es usar el parse user requestpasswordreset(email) método de back4app para enviar un correo electrónico de restablecimiento de contraseña al usuario cuando un usuario solicita un restablecimiento de contraseña con back4app back4app verifica que el correo electrónico exista en la base de datos si se encuentra el correo electrónico, se envía un correo electrónico de restablecimiento al usuario el correo electrónico contiene un enlace con un token seguro cuando el usuario hace clic en el enlace, es dirigido a una página de restablecimiento de contraseña después de establecer una nueva contraseña, pueden iniciar sesión con sus nuevas credenciales en la aplicación back4gram, la funcionalidad de restablecimiento de contraseña se implementa de manera similar en resetpasswordpage js , utilizando los mismos métodos de api de back4app, pero potencialmente con componentes de ui más avanzados o características adicionales ahora que hemos implementado las características básicas de autenticación, centrémonos en la gestión de sesiones proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 6 – gestión y persistencia de sesiones uno de los aspectos clave de cualquier sistema de autenticación es la gestión adecuada de sesiones esto asegura que los usuarios permanezcan conectados mientras navegan por su aplicación y que sus sesiones sean seguras creamos una versión simplificada de la página de feed para demostrar la verificación y gestión de sesiones crea un archivo llamado 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 verificación de autenticación verifica que el usuario haya iniciado sesión antes de mostrar el contenido redirección automática redirige a la página de inicio de sesión si no se encuentra una sesión de usuario funcionalidad de cierre de sesión permite al usuario cerrar sesión y limpiar su sesión visualización de información del usuario muestra información sobre el usuario que ha iniciado sesión actualmente entendiendo la gestión de sesiones de back4app back4app maneja las sesiones de varias maneras almacenamiento automático de sesiones el sdk de parse almacena automáticamente el token de sesión después del inicio de sesión acceso al usuario actual puedes acceder al usuario actual con parse user current() expiración de sesión las sesiones generalmente expiran después de un período establecido (configurable en back4app) cerrar sesión puedes finalizar una sesión con parse user logout() en una aplicación de producción como back4gram, la gestión de sesiones es a menudo más compleja en el messagespage js archivo de back4gram, podemos ver cómo se verifica la autenticación al principio del 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]); este patrón de verificación de autenticación a nivel de componente es común en aplicaciones react que utilizan back4app consideraciones de seguridad de sesión al implementar la gestión de sesiones con back4app, considera estas prácticas de seguridad invalidación automática de sesiones configura back4app para invalidar sesiones después de un cierto período de inactividad almacenamiento seguro asegúrate de que los tokens de sesión se almacenen de forma segura (el sdk de parse maneja esto automáticamente) solo https siempre usa https para prevenir la interceptación de tokens de sesión cerrar sesión en acciones sensibles requiere re autenticación para operaciones sensibles como cambiar contraseñas ahora veamos cómo implementar la gestión de perfiles para completar nuestro sistema de autenticación proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 7 – agregando gestión de perfiles de usuario la última parte de nuestro sistema de autenticación es la gestión del perfil de usuario esto permite a los usuarios ver y actualizar su información de perfil crea un archivo llamado 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()); } cuando creas un nuevo parse file , back4app toma tu archivo (imagen, documento, etc ) lo sube a un almacenamiento seguro devuelve una referencia que se puede almacenar con tu objeto de usuario hace que el archivo sea accesible a través de una url añadiendo campos de usuario personalizados la clase parse user de back4app se puede extender con campos personalizados más allá de los predeterminados en nuestro ejemplo, hemos añadido bio un campo de texto para descripciones de usuario avatar un campo de archivo para fotos de perfil puedes añadir cualquier campo personalizado que necesites para los perfiles de usuario de tu aplicación user set('bio', bio); en la aplicación back4gram, el profilepage js implementa una funcionalidad similar pero con más características y una interfaz de usuario más compleja incluye campos adicionales como conteos de seguidores, estadísticas de publicaciones y un manejo de imágenes más robusto proyecto back4gram encuentra aquí el código completo para un proyecto de muestra de red social construido con back4app paso 8 – probando y asegurando su sistema de autenticación ahora que hemos construido nuestro sistema de autenticación, hablemos sobre cómo probarlo y asegurarlo adecuadamente probando flujos de autenticación al probar su sistema de autenticación, debe verificar cada uno de estos flujos registro de usuario pruebe que los usuarios pueden crear cuentas con credenciales válidas validación de entrada verifique que aparezcan errores apropiados para entradas no válidas proceso de inicio de sesión asegúrese de que los usuarios puedan iniciar sesión con credenciales correctas inicio de sesión fallido verifique que aparezcan errores apropiados para credenciales incorrectas restablecimiento de contraseña confirme que el flujo de restablecimiento de contraseña funcione de extremo a extremo persistencia de sesión verifique que los usuarios permanezcan conectados entre visitas a la página proceso de cierre de sesión asegúrese de que los usuarios puedan cerrar sesión correctamente y que las sesiones se terminen vulnerabilidades de seguridad comunes a evitar al construir sistemas de autenticación, tenga en cuenta estos problemas de seguridad comunes almacenamiento de contraseñas nunca almacene contraseñas en texto plano back4app maneja esto automáticamente por usted ataques de fuerza bruta implemente limitación de tasa para los intentos de inicio de sesión back4app proporciona esta funcionalidad cross site scripting (xss) sane los inputs de los usuarios para prevenir la inyección de scripts cross site request forgery (csrf) use tokens adecuados para verificar la autenticidad de las solicitudes referencias directas a objetos inseguros no exponga ids o referencias sensibles en las urls mejores prácticas de seguridad de back4app back4app proporciona varias características de seguridad que debe aprovechar 1 permisos a nivel de clase (clps) en tu panel de back4app, puedes establecer permisos a nivel de clase para controlar quién puede leer, escribir y eliminar objetos ve a tu panel de back4app navega a base de datos → navegador haz clic en el botón "seguridad" para tu clase de usuario configura los permisos adecuadamente \[imagen pantalla de permisos a nivel de clase de back4app mostrando la configuración de seguridad de la clase de usuario] para la clase de usuario, la configuración típica incluye acceso de lectura público solo para campos específicos (nombre de usuario, avatar) sin acceso público para escribir o eliminar solo los usuarios autenticados pueden actualizar sus propios registros 2 listas de control de acceso (acls) para objetos individuales, puedes usar acls para controlar el acceso // 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(); esto asegura que solo el usuario que creó un objeto puede acceder o modificarlo 3 uso de la clave maestra back4app proporciona una clave maestra que omite las verificaciones de seguridad nunca expongas esto en el código del lado del cliente // never do this in client side code parse cloud usemasterkey(); // this should only be used in cloud code en su lugar, para operaciones que requieren privilegios elevados, utiliza cloud functions 4 verificación de correo electrónico habilita la verificación de correo electrónico en la configuración de back4app para asegurarte de que los usuarios proporcionen direcciones de correo electrónico válidas ve a tu panel de back4app navega a configuración de la aplicación → configuración de correo electrónico configura tu adaptador de correo electrónico habilita la verificación de correo electrónico \[imagen pantalla de configuración de correo electrónico de back4app] 5 autenticación de dos factores para mayor seguridad, puedes implementar la autenticación de dos factores utilizando las cloud functions de back4app esto requiere que los usuarios proporcionen una segunda forma de verificación (típicamente un código enviado a su teléfono o correo electrónico) al iniciar sesión implementación de limitación de tasa para protegerse contra ataques de fuerza bruta, puedes implementar la limitación de tasa utilizando cloud functions // 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; } }); conclusión en este tutorial, has construido un sistema de autenticación integral para una aplicación de red social utilizando back4app has implementado características de registro de usuarios, inicio de sesión, restablecimiento de contraseña y gestión de perfiles, todo impulsado por las capacidades de gestión de usuarios integradas de back4app recapitulemos lo que has aprendido sistema de gestión de usuarios de back4app has aprendido cómo el servidor parse de back4app proporciona autenticación de usuario integrada con la parse user clase registro de usuarios has implementado un formulario de registro que crea nuevas cuentas de usuario en la base de datos de back4app inicio de sesión de usuarios has creado un sistema de inicio de sesión que autentica a los usuarios y gestiona sesiones restablecimiento de contraseña has añadido una función de restablecimiento de contraseña segura que envía correos electrónicos de recuperación gestión de sesiones has aprendido cómo mantener sesiones de usuario y proteger rutas gestión de perfiles has construido una página de perfil que permite a los usuarios actualizar su información y subir fotos de perfil mejores prácticas de seguridad has explorado cómo asegurar tu sistema de autenticación utilizando las características de seguridad de back4app con back4app, pudiste concentrarte en crear una gran experiencia de usuario en lugar de construir una infraestructura de backend compleja el servidor parse que impulsa back4app proporcionó todas las api de autenticación necesarias, al mismo tiempo que aseguraba que los datos de tus usuarios permanecieran seguros el sistema de autenticación que has construido forma la base de tu aplicación de red social con esto en su lugar, ahora puedes expandir tu aplicación añadiendo características como publicaciones, comentarios, me gusta y mensajería directa, todo utilizando back4app como tu servicio de backend próximos pasos integración de inicio de sesión social agrega inicio de sesión con google, facebook u otros proveedores utilizando las capacidades de oauth de back4app seguridad mejorada implementa autenticación de dos factores para mayor seguridad roles de usuario configura control de acceso basado en roles para diferentes tipos de usuarios características en tiempo real agrega mensajería y notificaciones en tiempo real utilizando live query de back4app para el código completo de la aplicación de red social back4gram, puedes consultar el repositorio de github https //github com/templates back4app/back4gram los poderosos servicios de backend de back4app y la integración de parse server lo convierten en una excelente opción para construir aplicaciones de red social seguras y escalables al aprovechar sus capacidades de gestión de usuarios integradas, puedes crear un sistema de autenticación robusto con un esfuerzo mínimo, lo que te permite centrarte en crear características únicas que hagan que tu aplicación se destaque