Project Templates
Social Network
Система аутентификации для вашей социальной сети
52 мин
введение в этом учебном пособии вы узнаете, как реализовать комплексную систему аутентификации для вашего веб приложения социальной сети, используя back4app в качестве вашего серверного решения вы создадите функциональность для регистрации пользователей, входа в систему, сброса пароля и управления сессиями критически важные функции для любого современного социального приложения back4app это платформа backend as a service (baas), построенная на parse server, которая позволяет разработчикам создавать масштабируемые приложения без управления серверной инфраструктурой встроенные возможности аутентификации пользователей делают ее идеальной для быстрого внедрения безопасных систем управления пользователями к концу этого учебного пособия вы создадите полностью функциональную систему аутентификации, аналогичную той, что используется в back4gram, приложении социальной сети вы реализуете регистрацию пользователей с валидацией, безопасный вход, восстановление пароля и постоянные сессии по всему приложению, предоставляя вашим пользователям бесшовный опыт, сохраняя при этом безопасность их аккаунтов проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app предварительные требования чтобы завершить этот учебник, вам потребуется учетная запись back4app вы можете зарегистрироваться для получения бесплатной учетной записи на back4app com https //www back4app com настроенный проект back4app вы можете узнать, как создать новый проект, следуя нашему руководству по началу работы с back4app https //www back4app com/docs/get started/welcome установленный node js на вашем локальном компьютере базовые знания javascript, react js и концепций restful api знакомство с современными концепциями веб разработки (компоненты, управление состоянием и т д ) шаг 1 – понимание системы управления пользователями back4app перед тем как погрузиться в код, важно понять, как back4app обрабатывает управление пользователями back4app построен на parse server, который предоставляет специальный parse user класс, предназначенный специально для аутентификации класс parse user класс parse user в back4app расширяет стандартный объект parse с специализированной функциональностью для аутентификации пользователей он включает несколько встроенных полей имя пользователя уникальный идентификатор для пользователя (обязательно) пароль пароль пользователя (обязательно для регистрации, но не хранится в доступной форме) электронная почта адрес электронной почты пользователя (необязательно, но рекомендуется) emailverified логическое значение, указывающее, подтвердил ли пользователь свою электронную почту authdata данные аутентификации для аутентификации третьих сторон вы также можете добавить пользовательские поля для хранения дополнительной информации о пользователе, такой как фотографии профиля, биографии или любые другие данные, специфичные для пользователя управление сессиями когда пользователь входит в систему, back4app создает токен сессии, который идентифицирует сессию пользователя этот токен используется для аутентификации последующих запросов без необходимости повторного входа пользователя в систему токен сессии автоматически управляется parse sdk, но также может быть вручную контролируем, если это необходимо вот как работает поток сессии пользователь предоставляет учетные данные (имя пользователя/электронная почта и пароль) back4app проверяет учетные данные если данные действительны, back4app создает токен сессии токен хранится локально (обычно в localstorage или аналогичном механизме) токен включается в последующие api запросы для аутентификации пользователя давайте посмотрим, как это реализовано в приложении back4gram код инициализации parse обычно выглядит так // initialize parse with your back4app credentials parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com/"; эта настройка в приложении back4gram позволяет всем компонентам получать доступ к sdk parse и делать аутентифицированные запросы после входа пользователя функции безопасности back4app предоставляет несколько функций безопасности для управления пользователями безопасное хранение паролей пароли никогда не хранятся в открытом виде, а автоматически хэшируются и солятся управление сессиями пользовательские сессии могут управляться и аннулироваться через панель управления back4app списки контроля доступа (acl) вы можете контролировать, кто может читать или записывать конкретные объекты проверка электронной почты back4app может отправлять пользователям письма для подтверждения сброс пароля встроенная функциональность для безопасного сброса паролей теперь, когда мы понимаем основы, давайте перейдем к настройке нашего проекта проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 2 – настройка вашего проекта чтобы продемонстрировать, как реализовать аутентификацию с помощью back4app, мы создадим упрощенную версию приложения социальной сети back4gram создание нового react приложения сначала давайте создадим новое react приложение откройте терминал и выполните npx create react app social network auth cd social network auth установка необходимых пакетов далее мы установим необходимые пакеты npm install parse react router dom @chakra ui/react @emotion/react @emotion/styled framer motion эти пакеты предоставляют parse javascript sdk для back4app react router dom для маршрутизации страниц @chakra ui/react библиотека компонентов для создания пользовательского интерфейса структура проекта давайте настроим базовую файловую структуру для нашей системы аутентификации src/ ├── components/ │ └── ui/ │ ├── field js │ └── toaster js ├── pages/ │ ├── signuppage js │ ├── loginpage js │ ├── resetpasswordpage js │ ├── profilepage js │ └── feedpage js ├── app js └── index js настройка parse sdk теперь давайте инициализируем parse в нашем приложении создайте файл с именем 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; замените your app id и your javascript key на ваши учетные данные проекта back4app вы можете найти их в вашей панели управления back4app в разделе настройки приложения > безопасность и ключи далее давайте обновим src/index js для импорта нашей конфигурации 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> ); настройка маршрутов теперь давайте настроим базовую структуру маршрутизации в 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; создание компонентов пользовательского интерфейса прежде чем мы начнем создавать страницы аутентификации, давайте создадим несколько многоразовых компонентов пользовательского интерфейса сначала давайте создадим 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 } }; затем создайте 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> ); }; теперь мы готовы реализовать нашу систему аутентификации! проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 3 – создание системы регистрации пользователей давайте начнем с реализации страницы регистрации эта страница позволит новым пользователям создать учетную запись, предоставив имя пользователя, адрес электронной почты и пароль создайте файл с названием 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; этот код создает форму регистрации со следующими функциями проверка формы проверяет, что все обязательные поля заполнены правильно перед отправкой переключатель видимости пароля позволяет пользователям видеть, что они вводят обработка ошибок отображает соответствующие сообщения об ошибках для проверки и неудач регистрации состояние загрузки показывает индикатор загрузки во время процесса регистрации понимание процесса регистрации пользователей back4app ключевая часть этого кода — это handlesignup функция, которая использует класс back4app parse user для создания нового пользователя const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); когда вы вызываете signup() , back4app проверяет предоставленные данные безопасно хэширует пароль создает нового пользователя в базе данных создает и возвращает токен сессии токен сессии автоматически сохраняется sdk parse после успешной регистрации пользователь автоматически входит в систему, поэтому мы можем перенаправить его прямо на страницу ленты в приложении back4gram это реализовано аналогичным образом в signuppage js основное отличие заключается в том, что реализация back4gram использует более продвинутые компоненты пользовательского интерфейса и может включать дополнительные поля или логику валидации с завершением функциональности регистрации давайте перейдем к реализации функциональности входа проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 4 – реализация входа пользователя теперь давайте создадим страницу входа, которая позволит пользователям аутентифицироваться с помощью своих учетных данных создайте файл с именем 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; эта страница входа имеет следующие функции авто перенаправление если пользователь уже вошел в систему, его автоматически перенаправляют на страницу ленты валидация формы обеспечивает наличие имени пользователя и пароля перед отправкой обработка ошибок отображает соответствующие сообщения об ошибках для неудачных попыток входа состояние загрузки показывает индикатор загрузки во время процесса входа ссылка для сброса пароля предоставляет ссылку на страницу сброса пароля понимание процесса входа в back4app ключевые части этого кода проверка существующего вошедшего пользователя с помощью parse user current() вход пользователя с помощью parse user login(username, password) когда пользователь входит в систему с помощью back4app учетные данные отправляются на сервер для проверки если действительны, создается и возвращается токен сессии sdk parse автоматически сохраняет этот токен объект пользователя возвращается с данными текущего пользователя сохраненный токен сессии затем автоматически используется sdk parse для всех последующих запросов, позволяя пользователю оставаться в системе в приложении back4gram система входа реализована аналогично в loginpage js , но с более продвинутыми компонентами пользовательского интерфейса и потенциально дополнительными функциями, такими как варианты входа через социальные сети теперь давайте перейдем к реализации функции сброса пароля проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 5 – функция сброса пароля далее давайте создадим страницу сброса пароля, которая позволит пользователям восстановить свои аккаунты, если они забудут свои пароли создайте файл с именем 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; эта страница сброса пароля включает в себя проверка электронной почты обеспечивает, что предоставлен действительный формат электронной почты состояние успеха показывает сообщение об успехе после отправки письма для сброса пароля обработка ошибок отображает соответствующие сообщения об ошибках, если запрос на сброс не удался состояние загрузки показывает индикатор загрузки во время процесса запроса на сброс понимание процесса сброса пароля back4app ключевая часть этого кода заключается в использовании метода back4app parse user requestpasswordreset(email) для отправки письма для сброса пароля пользователю когда пользователь запрашивает сброс пароля с помощью back4app back4app проверяет, существует ли электронная почта в базе данных если электронная почта найдена, пользователю отправляется письмо для сброса пароля письмо содержит ссылку с безопасным токеном когда пользователь нажимает на ссылку, его перенаправляют на страницу сброса пароля после установки нового пароля они могут войти в систему с новыми учетными данными в приложении back4gram функция сброса пароля реализована аналогично в resetpasswordpage js , используя те же методы api back4app, но потенциально с более продвинутыми компонентами пользовательского интерфейса или дополнительными функциями теперь, когда мы реализовали основные функции аутентификации, давайте сосредоточимся на управлении сессиями проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 6 – управление сессиями и их сохранение одним из ключевых аспектов любой системы аутентификации является правильное управление сессиями это обеспечивает то, что пользователи остаются в системе во время навигации по вашему приложению и что их сессии безопасны давайте создадим упрощенную версию страницы ленты, чтобы продемонстрировать проверку и управление сессиями создайте файл с именем 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; эта страница ленты реализует проверка аутентификации проверяет, что пользователь вошел в систему перед отображением контента автоматический редирект перенаправляет на страницу входа, если сессия пользователя не найдена функциональность выхода позволяет пользователю выйти из системы и очистить свою сессию отображение информации о пользователе показывает информацию о текущем вошедшем пользователе понимание управления сессиями back4app back4app обрабатывает сессии несколькими способами автоматическое хранение сессий sdk parse автоматически сохраняет токен сессии после входа в систему доступ к текущему пользователю вы можете получить доступ к текущему пользователю с помощью parse user current() истечение срока действия сессии сессии обычно истекают через установленный период (настраиваемый в back4app) выход вы можете завершить сессию с помощью parse user logout() в производственном приложении, таком как back4gram, управление сессиями часто более сложное в файле messagespage js , мы можем увидеть, как проверяется аутентификация в начале компонента 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]); этот шаблон проверки аутентификации на уровне компонента распространен в приложениях react, использующих back4app соображения по безопасности сессий при реализации управления сессиями с back4app учитывайте следующие практики безопасности автоматическая недействительность сессии настройте back4app на недействительность сессий после определенного периода бездействия безопасное хранение убедитесь, что токены сессий хранятся безопасно (sdk parse обрабатывает это автоматически) только https всегда используйте https, чтобы предотвратить перехват токенов сессий выход при выполнении чувствительных действий требуйте повторной аутентификации для чувствительных операций, таких как изменение паролей теперь давайте рассмотрим, как реализовать управление профилем, чтобы завершить нашу систему аутентификации проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 7 – добавление управления профилем пользователя последний элемент нашей системы аутентификации управление профилем пользователя это позволяет пользователям просматривать и обновлять информацию о своем профиле создайте файл с названием 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()); } когда вы создаете новый parse file , back4app берет ваш файл (изображение, документ и т д ) загружает его в безопасное хранилище возвращает ссылку, которую можно сохранить с вашим объектом пользователя делает файл доступным по url добавление пользовательских полей пользователя back4app's parse user класс можно расширить пользовательскими полями помимо стандартных в нашем примере мы добавили bio текстовое поле для описания пользователей avatar поле для файлов с фотографиями профиля вы можете добавить любые пользовательские поля, которые вам нужны для профилей пользователей вашего приложения user set('bio', bio); в приложении back4gram, profilepage js реализует аналогичную функциональность, но с большим количеством функций и более сложным интерфейсом оно включает дополнительные поля, такие как количество подписчиков, статистика постов и более надежная обработка изображений проект back4gram найдите здесь полный код для образца проекта социальной сети созданного с помощью back4app шаг 8 – тестирование и защита вашей системы аутентификации теперь, когда мы создали нашу систему аутентификации, давайте обсудим, как правильно ее протестировать и защитить тестирование потоков аутентификации при тестировании вашей системы аутентификации вы должны проверить каждый из этих потоков регистрация пользователя проверьте, что пользователи могут создавать учетные записи с действительными учетными данными проверка ввода убедитесь, что для недействительных вводов появляются соответствующие ошибки процесс входа убедитесь, что пользователи могут войти с правильными учетными данными неудачный вход проверьте, что для неправильных учетных данных появляются соответствующие ошибки сброс пароля подтвердите, что процесс сброса пароля работает от начала до конца сохранение сессии убедитесь, что пользователи остаются в системе между посещениями страниц процесс выхода убедитесь, что пользователи могут правильно выйти, и сессии завершаются общие уязвимости безопасности, которых следует избегать при создании систем аутентификации будьте внимательны к этим общим проблемам безопасности хранение паролей никогда не храните пароли в открытом виде back4app обрабатывает это автоматически атаки методом перебора реализуйте ограничение частоты для попыток входа back4app предоставляет эту функциональность межсайтовый скриптинг (xss) очистите пользовательские вводы, чтобы предотвратить инъекцию скриптов межсайтовая подделка запросов (csrf) используйте правильные токены для проверки подлинности запросов небезопасные прямые ссылки на объекты не раскрывайте чувствительные идентификаторы или ссылки в url лучшие практики безопасности back4app back4app предоставляет несколько функций безопасности, которые вы должны использовать 1 разрешения на уровне классов (clp) в вашей панели управления back4app вы можете установить разрешения на уровне класса, чтобы контролировать, кто может читать, записывать и удалять объекты перейдите в свою панель управления back4app перейдите в базу данных → обозреватель нажмите кнопку "безопасность" для вашего класса пользователей настройте разрешения соответствующим образом \[изображение экран разрешений на уровне класса back4app, показывающий настройки безопасности класса пользователей] для класса пользователей типичные настройки включают общий доступ к чтению только для определенных полей (имя пользователя, аватар) нет общего доступа на запись или удаление только аутентифицированные пользователи могут обновлять свои собственные записи 2 списки контроля доступа (acl) для отдельных объектов вы можете использовать acl для контроля доступа // 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(); это гарантирует, что только пользователь, создавший объект, может получить к нему доступ или изменить его 3 использование мастер ключа back4app предоставляет мастер ключ, который обходит проверки безопасности никогда не раскрывайте его в коде на стороне клиента // never do this in client side code parse cloud usemasterkey(); // this should only be used in cloud code вместо этого для операций, требующих повышенных привилегий, используйте облачные функции 4 подтверждение электронной почты включите подтверждение электронной почты в настройках back4app, чтобы убедиться, что пользователи предоставляют действительные адреса электронной почты перейдите на панель управления back4app перейдите в настройки приложения → настройки электронной почты настройте адаптер электронной почты включите подтверждение электронной почты \[изображение экран настройки электронной почты back4app] 5 двухфакторная аутентификация для дополнительной безопасности вы можете реализовать двухфакторную аутентификацию с использованием облачных функций back4app это требует от пользователей предоставления второго способа проверки (обычно кода, отправленного на их телефон или электронную почту) при входе в систему реализация ограничения скорости чтобы защититься от атак методом подбора, вы можете реализовать ограничение скорости с использованием облачных функций // 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; } }); заключение в этом учебном пособии вы создали комплексную систему аутентификации для приложения социальной сети, используя back4app вы реализовали функции регистрации пользователей, входа в систему, сброса пароля и управления профилем, все это с помощью встроенных возможностей управления пользователями back4app давайте подведем итоги того, что вы узнали система управления пользователями back4app вы узнали, как сервер parse от back4app предоставляет встроенную аутентификацию пользователей с помощью класса parse user регистрация пользователей вы реализовали форму регистрации, которая создает новые учетные записи пользователей в базе данных back4app вход пользователей вы создали систему входа, которая аутентифицирует пользователей и управляет сессиями сброс пароля вы добавили безопасную функцию сброса пароля, которая отправляет письма для восстановления управление сессиями вы узнали, как поддерживать пользовательские сессии и защищать маршруты управление профилем вы создали страницу профиля, которая позволяет пользователям обновлять свою информацию и загружать фотографии профиля лучшие практики безопасности вы изучили, как защитить свою систему аутентификации, используя функции безопасности back4app с помощью back4app вы смогли сосредоточиться на создании отличного пользовательского опыта, а не на построении сложной серверной инфраструктуры сервер parse, который поддерживает back4app, предоставил все необходимые api для аутентификации, одновременно обеспечивая безопасность ваших пользовательских данных система аутентификации, которую вы создали, является основой вашего приложения социальной сети с этим в наличии вы можете теперь расширить ваше приложение, добавив такие функции, как публикации, комментарии, лайки и прямые сообщения, используя back4app в качестве вашего серверного решения следующие шаги интеграция социальной авторизации добавьте вход с помощью google, facebook или других провайдеров, используя возможности oauth от back4app улучшенная безопасность реализуйте двухфакторную аутентификацию для дополнительной безопасности роли пользователей настройте контроль доступа на основе ролей для различных типов пользователей функции в реальном времени добавьте обмен сообщениями в реальном времени и уведомления, используя live query от back4app для полного кода приложения социальной сети back4gram вы можете ознакомиться с репозиторием на github https //github com/templates back4app/back4gram мощные серверные услуги back4app и интеграция с parse server делают его отличным выбором для создания безопасных и масштабируемых приложений социальной сети используя его встроенные возможности управления пользователями, вы можете создать надежную систему аутентификации с минимальными усилиями, что позволит вам сосредоточиться на создании уникальных функций, которые выделят ваше приложение