مدیریت AUTH در برنامه های REACT با استفاده از NANOSTORES و Context API

Summarize this content to 400 words in Persian Lang
در روزهای ابتدایی ساختن برنامه های وب کامل پشته با ReactJs، متوجه شدم که چگونه احراز هویت در فرانت اند را مدیریت کنم. منظورم این است که بعد از دریافت توکن دسترسی خود از باطن چه کاری باید انجام دهید؟ چگونه حالت ورود را حفظ می کنید؟
اکثر مبتدیان فرض می کنند “اوه، فقط توکن خود را در حالت ذخیره کنید”. اما من به سرعت متوجه شدم که این بهترین راه حل نیست، و نه حتی یک راه حل، زیرا همانطور که اکثر توسعه دهندگان ReactJs می دانند، وضعیت موقتی است زیرا هر بار که صفحه را به روز می کنید پاک می شود و ما قطعاً می توانیم. هر بار که آنها به روز می شوند، ورود کاربر را ندارند.
به سرعت به جلو تا کنون که کمی تجربه در ساخت برنامه های فول استک در react به دست آورده ام، رویکرد توسعه دهندگان باتجربه تر برای احراز هویت و تکرار این فرآیند در دو برنامه دیگر را مطالعه کرده ام، می خواهم راهنمایی در مورد چگونگی من ارائه دهم. در حال حاضر آن را اداره کند. برخی از مردم ممکن است فکر نکنند که این بهترین راه است، اما من آن را به عنوان روش خود در حال حاضر پذیرفته ام و آماده یادگیری روش های دیگر مورد استفاده توسعه دهندگان دیگر هستم.
مرحله اول
شما ایمیل و رمز عبور خود را (با فرض اینکه از احراز هویت اولیه ایمیل و رمز عبور استفاده می کنید) را برای شروع فرآیند احراز هویت به پشتیبان ارسال کرده اید. من در مورد نحوه استفاده از auth در backend صحبت نخواهم کرد زیرا این مقاله در مورد نحوه رسیدگی به auth فقط در frontend است. من به بخشی که در پاسخ HTTP توکن دریافت کرده اید می پرم. در زیر یک نمونه کد از یک جزء فرم ورود ساده است که ایمیل و رمز عبور را به سرور ارسال می کند و رمز و اطلاعات کاربر را در پاسخ دریافت می کند. اکنون برای سادگی، مقادیر فرم من با حالت مدیریت می شود، بهتر است از یک کتابخانه قوی مانند فرمیک برای برنامه های تولیدی استفاده کنم.
import axios from ‘axios’
import { useState } from “react”
export default function LoginForm() {
const [email, setEmail] = useState(“”)
const [password, setPassword] = useState(“”)
const handleSubmit = async() => {
try {
const response = await axios.post(“/api/auth/login”, { email, password })
if (response?.status !== 200) {
throw new Error(“Failed login”)
}
const token = response?.data?.token
const userInfo = response?.data?.userInfo
} catch (error) {
throw error
}
}
return(
)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله دوم
کل برنامه خود یا فقط قسمت هایی که نیاز به دسترسی به وضعیت احراز هویت دارند را در یک ارائه دهنده زمینه Auth بپیچید. این کار معمولا در روت شما انجام می شود App.jsx فایل اگر نمی دانید API متنی چیست، به راحتی می توانید اسناد Reactjs را بررسی کنید. مثالهای زیر یک مؤلفه ارائهدهنده AuthContext ایجاد شده را نشان میدهند. سپس وارد می شود App.jsx و برای بسته بندی RouterProvider بازگردانده شده در مولفه App استفاده می شود، در نتیجه وضعیت احراز هویت از هر نقطه در برنامه قابل دسترسی است.
import { createContext } from “react”;
export const AuthContext = createContext(null)
export default function AuthProvider({children}) {
return(
{children}
)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
import React from “react”;
import { createBrowserRouter, RouterProvider } from “react-router-dom”;
import AuthProvider from “./AuthContext”;
const router = createBrowserRouter([
// your routes here
])
function App() {
return(
)
}
export default App
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله سوم
در زمینه احراز هویت، باید دو متغیر حالت، “isLoggedIn” و “authenticatedUser” را مقداردهی اولیه کنید. حالت اول یک نوع بولی است که ابتدا روی “نادرست” تنظیم می شود و پس از تایید ورود به “true” به روز می شود. متغیر حالت دوم برای ذخیره اطلاعات وارد شده کاربر مانند نام، ایمیل و غیره استفاده میشود. این متغیرهای حالت باید در مقدار ارائهدهنده در مولفه متنی بازگردانده شده گنجانده شوند تا بتوانند در سراسر برنامه برای رندر شرطی قابل دسترسی باشند. .
import { createContext, useState } from “react”;
export const AuthContext = createContext(null)
export default function AuthProvider({children}) {
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [authenticatedUser, setAuthenticatedUser] = useState(null)
const values = {
isLoggedIn,
authenticatedUser,
setAuthenticatedUser
}
return(
{children}
)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله چهارم
Nanostores بسته ای برای مدیریت وضعیت در برنامه های جاوا اسکریپت است. این بسته یک API ساده برای مدیریت مقادیر حالت در چندین مؤلفه با مقداردهی اولیه آن در یک فایل جداگانه و وارد کردن آن در هر مؤلفه ای که می خواهید از وضعیت استفاده کنید یا آن را به روز کنید، ارائه می دهد. اما، به منظور ذخیره رمز تأیید دریافتی خود در پاسخ HTTP در مرحله اول، از نانواستورها/مداوم استفاده خواهید کرد. این بسته با ذخیره آن در localStorage وضعیت شما را حفظ می کند، به این ترتیب وقتی صفحه را به روز می کنید پاک نمی شود. @nanostores/react یک react ادغام خاص برای نانواستورها است، آن را در دسترس قرار می دهد useStore قلاب برای استخراج مقادیر از حالت نانوذخیره.
بنابراین اکنون می توانید ادامه دهید و:
بسته های زیر را نصب کنید: nanostores، @nanostores/persistent و @nanostores/react.
در یک فایل جداگانه به نام user.atom.js یا هر چیزی که برای نام آن انتخاب می کنید، یک فروشگاه «authToken» و یک فروشگاه «user» را با استفاده از nanostores/persistent مقداردهی اولیه کنید.
آنها را به فایل مؤلفه فرم ورود خود وارد کنید و وضعیت را با رمز و داده های کاربر دریافت شده در پاسخ ورود خود به روز کنید.
npm i nanostores @nanostores/persistent @nanostores/react
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
import { persistentMap } from ‘@nanostores/persistent’
export const authToken = persistentMap(‘token’, null)
export const user = persistentMap(‘user’, null)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
import { authToken, user } from ‘./user.atom’
const handleSubmit = async() => {
try {
const response = await axios.post(“/api/auth/login”, { email, password })
if (response?.status !== 200) {
throw new Error(“Failed login”)
}
const token = response?.data?.token
const userInfo = response?.data?.userInfo
authToken.set(token)
user.set(userInfo)
} catch (error) {
throw error
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله پنجم
اکنون، در زمینه احراز هویت که برنامه شما را میپیچد، باید مطمئن شوید که توکن و وضعیت کاربر بهروزرسانی میشوند و در کل برنامه شما در دسترس هستند. برای رسیدن به این هدف باید:
ذخیرههای «authToken» و «user» را وارد کنید.
در ابتدا یک قلاب useEffect، در داخل قلاب، یک تابع 'checkLogin()' ایجاد کنید که بررسی می کند آیا توکن در فروشگاه 'authToken' وجود دارد یا خیر، اگر وجود دارد، یک تابع را اجرا کنید تا بررسی کنید که آیا منقضی شده است یا خیر. بر اساس نتایج بررسی، شما یا کاربر را به صفحه ورود هدایت میکنید تا احراز هویت شود یا… حالت «isLoggedIn» را روی true تنظیم کنید. اکنون برای اطمینان از اینکه وضعیت ورود به سیستم بیشتر ردیابی میشود، میتوان این هوک را طوری تنظیم کرد که هر بار که مسیر فعلی تغییر میکند، اجرا شود، به این ترتیب، کاربر میتواند در صورت منقضی شدن توکن خود در حین تعامل با برنامه، اخراج شود یا به صفحه ورود هدایت شود. .
یک قلاب useEffect دیگر را راهاندازی کنید که حاوی تابعی برای واکشی اطلاعات کاربر از باطن با استفاده از رمز موجود در فروشگاه authToken هر بار که برنامه بارگیری یا بهروزرسانی میشود، باشد. اگر پاسخ موفقیت آمیزی دریافت کردید، وضعیت “isLoggedIn” را روی true تنظیم کنید و وضعیت “authenticatedUser” و “user” را با اطلاعات کاربر دریافت شده در پاسخ به روز کنید.
در زیر به روز رسانی شده است AuthProvider فایل کامپوننت
import { createContext, useState } from “react”;
import { authToken, user } from ‘./user.atom’;
import { useStore } from “@nanostores/react”;
import { useNavigate, useLocation } from “react-router-dom”;
import axios from “axios”;
export const AuthContext = createContext(null)
export default function AuthProvider({children}) {
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [authenticatedUser, setAuthenticatedUser] = useState(null)
const token = useStore(authToken)
const navigate = useNavigate()
const { pathname } = useLocation()
function isTokenExpired() {
// verify token expiration and return true or false
}
// Hook to check if user is logged in
useEffect(() => {
async function checkLogin () {
if (token) {
const expiredToken = isTokenExpired(token);
if (expiredToken) {
// clear out expired token and user from store and navigate to login page
authToken.set(null)
user.set(null)
setIsLoggedIn(false);
navigate(“/login”);
return;
}
}
};
checkLogin()
}, [pathname])
// Hook to fetch current user info and update state
useEffect(() => {
async function fetchUser() {
const response = await axios.get(“/api/auth/user”, {
headers: {
‘Authorization’: `Bearer ${token}`
}
})
if(response?.status !== 200) {
throw new Error(“Failed to fetch user data”)
}
setAuthenticatedUser(response?.data)
setIsLoggedIn(true)
}
fetchUser()
}, [])
const values = {
isLoggedIn,
authenticatedUser,
setAuthenticatedUser
}
return(
{children}
)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
نتیجه گیری
اکنون این دو قلاب useEffect ایجاد شده در مرحله پنج، مسئول مدیریت کل وضعیت اعتبار برنامه شما هستند. هر بار که یک بهروزرسانی انجام میدهید، آنها برای بررسی توکن شما در حافظه محلی اجرا میشوند، جدیدترین دادههای کاربر را مستقیماً از باطن بازیابی میکنند و وضعیت «isLoggedIn» و «authenticatedUser» شما را بهروزرسانی میکنند. میتوانید با وارد کردن «AuthContext» و «useContext» هوک از react و فراخوانی آنها در کامپوننت خود، از حالتهای موجود در هر مؤلفه استفاده کنید تا به مقادیر دسترسی داشته باشید و از آنها برای برخی رندرهای شرطی استفاده کنید.
import { useContext } from “react”;
import { AuthContext } from “./AuthContext”;
export default function MyLoggedInComponent() {
const { isLoggedIn, authenticatedUser } = useContext(AuthContext)
return(
{
isLoggedIn ?
Welcome {authenticatedUser?.name}
:
Login
}
>
)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
به یاد داشته باشید که در هنگام خروج، باید با قرار دادن null، فروشگاه “authToken” و “user” را پاک کنید. همچنین باید «isLoggedIn» را روی false و «authenticatedUser» را روی null تنظیم کنید.
با تشکر برای خواندن!
در روزهای ابتدایی ساختن برنامه های وب کامل پشته با ReactJs، متوجه شدم که چگونه احراز هویت در فرانت اند را مدیریت کنم. منظورم این است که بعد از دریافت توکن دسترسی خود از باطن چه کاری باید انجام دهید؟ چگونه حالت ورود را حفظ می کنید؟
اکثر مبتدیان فرض می کنند “اوه، فقط توکن خود را در حالت ذخیره کنید”. اما من به سرعت متوجه شدم که این بهترین راه حل نیست، و نه حتی یک راه حل، زیرا همانطور که اکثر توسعه دهندگان ReactJs می دانند، وضعیت موقتی است زیرا هر بار که صفحه را به روز می کنید پاک می شود و ما قطعاً می توانیم. هر بار که آنها به روز می شوند، ورود کاربر را ندارند.
به سرعت به جلو تا کنون که کمی تجربه در ساخت برنامه های فول استک در react به دست آورده ام، رویکرد توسعه دهندگان باتجربه تر برای احراز هویت و تکرار این فرآیند در دو برنامه دیگر را مطالعه کرده ام، می خواهم راهنمایی در مورد چگونگی من ارائه دهم. در حال حاضر آن را اداره کند. برخی از مردم ممکن است فکر نکنند که این بهترین راه است، اما من آن را به عنوان روش خود در حال حاضر پذیرفته ام و آماده یادگیری روش های دیگر مورد استفاده توسعه دهندگان دیگر هستم.
مرحله اول
شما ایمیل و رمز عبور خود را (با فرض اینکه از احراز هویت اولیه ایمیل و رمز عبور استفاده می کنید) را برای شروع فرآیند احراز هویت به پشتیبان ارسال کرده اید. من در مورد نحوه استفاده از auth در backend صحبت نخواهم کرد زیرا این مقاله در مورد نحوه رسیدگی به auth فقط در frontend است. من به بخشی که در پاسخ HTTP توکن دریافت کرده اید می پرم. در زیر یک نمونه کد از یک جزء فرم ورود ساده است که ایمیل و رمز عبور را به سرور ارسال می کند و رمز و اطلاعات کاربر را در پاسخ دریافت می کند. اکنون برای سادگی، مقادیر فرم من با حالت مدیریت می شود، بهتر است از یک کتابخانه قوی مانند فرمیک برای برنامه های تولیدی استفاده کنم.
import axios from 'axios'
import { useState } from "react"
export default function LoginForm() {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const handleSubmit = async() => {
try {
const response = await axios.post("/api/auth/login", { email, password })
if (response?.status !== 200) {
throw new Error("Failed login")
}
const token = response?.data?.token
const userInfo = response?.data?.userInfo
} catch (error) {
throw error
}
}
return(
)
}
مرحله دوم
کل برنامه خود یا فقط قسمت هایی که نیاز به دسترسی به وضعیت احراز هویت دارند را در یک ارائه دهنده زمینه Auth بپیچید. این کار معمولا در روت شما انجام می شود App.jsx
فایل اگر نمی دانید API متنی چیست، به راحتی می توانید اسناد Reactjs را بررسی کنید. مثالهای زیر یک مؤلفه ارائهدهنده AuthContext ایجاد شده را نشان میدهند. سپس وارد می شود App.jsx
و برای بسته بندی RouterProvider بازگردانده شده در مولفه App استفاده می شود، در نتیجه وضعیت احراز هویت از هر نقطه در برنامه قابل دسترسی است.
import { createContext } from "react";
export const AuthContext = createContext(null)
export default function AuthProvider({children}) {
return(
{children}
)
}
import React from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import AuthProvider from "./AuthContext";
const router = createBrowserRouter([
// your routes here
])
function App() {
return(
)
}
export default App
مرحله سوم
در زمینه احراز هویت، باید دو متغیر حالت، “isLoggedIn” و “authenticatedUser” را مقداردهی اولیه کنید. حالت اول یک نوع بولی است که ابتدا روی “نادرست” تنظیم می شود و پس از تایید ورود به “true” به روز می شود. متغیر حالت دوم برای ذخیره اطلاعات وارد شده کاربر مانند نام، ایمیل و غیره استفاده میشود. این متغیرهای حالت باید در مقدار ارائهدهنده در مولفه متنی بازگردانده شده گنجانده شوند تا بتوانند در سراسر برنامه برای رندر شرطی قابل دسترسی باشند. .
import { createContext, useState } from "react";
export const AuthContext = createContext(null)
export default function AuthProvider({children}) {
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [authenticatedUser, setAuthenticatedUser] = useState(null)
const values = {
isLoggedIn,
authenticatedUser,
setAuthenticatedUser
}
return(
{children}
)
}
مرحله چهارم
Nanostores بسته ای برای مدیریت وضعیت در برنامه های جاوا اسکریپت است. این بسته یک API ساده برای مدیریت مقادیر حالت در چندین مؤلفه با مقداردهی اولیه آن در یک فایل جداگانه و وارد کردن آن در هر مؤلفه ای که می خواهید از وضعیت استفاده کنید یا آن را به روز کنید، ارائه می دهد. اما، به منظور ذخیره رمز تأیید دریافتی خود در پاسخ HTTP در مرحله اول، از نانواستورها/مداوم استفاده خواهید کرد. این بسته با ذخیره آن در localStorage وضعیت شما را حفظ می کند، به این ترتیب وقتی صفحه را به روز می کنید پاک نمی شود. @nanostores/react یک react ادغام خاص برای نانواستورها است، آن را در دسترس قرار می دهد useStore
قلاب برای استخراج مقادیر از حالت نانوذخیره.
بنابراین اکنون می توانید ادامه دهید و:
-
بسته های زیر را نصب کنید: nanostores، @nanostores/persistent و @nanostores/react.
-
در یک فایل جداگانه به نام
user.atom.js
یا هر چیزی که برای نام آن انتخاب می کنید، یک فروشگاه «authToken» و یک فروشگاه «user» را با استفاده از nanostores/persistent مقداردهی اولیه کنید. -
آنها را به فایل مؤلفه فرم ورود خود وارد کنید و وضعیت را با رمز و داده های کاربر دریافت شده در پاسخ ورود خود به روز کنید.
npm i nanostores @nanostores/persistent @nanostores/react
import { persistentMap } from '@nanostores/persistent'
export const authToken = persistentMap('token', null)
export const user = persistentMap('user', null)
import { authToken, user } from './user.atom'
const handleSubmit = async() => {
try {
const response = await axios.post("/api/auth/login", { email, password })
if (response?.status !== 200) {
throw new Error("Failed login")
}
const token = response?.data?.token
const userInfo = response?.data?.userInfo
authToken.set(token)
user.set(userInfo)
} catch (error) {
throw error
}
}
مرحله پنجم
اکنون، در زمینه احراز هویت که برنامه شما را میپیچد، باید مطمئن شوید که توکن و وضعیت کاربر بهروزرسانی میشوند و در کل برنامه شما در دسترس هستند. برای رسیدن به این هدف باید:
-
ذخیرههای «authToken» و «user» را وارد کنید.
-
در ابتدا یک قلاب useEffect، در داخل قلاب، یک تابع 'checkLogin()' ایجاد کنید که بررسی می کند آیا توکن در فروشگاه 'authToken' وجود دارد یا خیر، اگر وجود دارد، یک تابع را اجرا کنید تا بررسی کنید که آیا منقضی شده است یا خیر. بر اساس نتایج بررسی، شما یا کاربر را به صفحه ورود هدایت میکنید تا احراز هویت شود یا… حالت «isLoggedIn» را روی true تنظیم کنید. اکنون برای اطمینان از اینکه وضعیت ورود به سیستم بیشتر ردیابی میشود، میتوان این هوک را طوری تنظیم کرد که هر بار که مسیر فعلی تغییر میکند، اجرا شود، به این ترتیب، کاربر میتواند در صورت منقضی شدن توکن خود در حین تعامل با برنامه، اخراج شود یا به صفحه ورود هدایت شود. .
-
یک قلاب useEffect دیگر را راهاندازی کنید که حاوی تابعی برای واکشی اطلاعات کاربر از باطن با استفاده از رمز موجود در فروشگاه authToken هر بار که برنامه بارگیری یا بهروزرسانی میشود، باشد. اگر پاسخ موفقیت آمیزی دریافت کردید، وضعیت “isLoggedIn” را روی true تنظیم کنید و وضعیت “authenticatedUser” و “user” را با اطلاعات کاربر دریافت شده در پاسخ به روز کنید.
در زیر به روز رسانی شده است AuthProvider
فایل کامپوننت
import { createContext, useState } from "react";
import { authToken, user } from './user.atom';
import { useStore } from "@nanostores/react";
import { useNavigate, useLocation } from "react-router-dom";
import axios from "axios";
export const AuthContext = createContext(null)
export default function AuthProvider({children}) {
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [authenticatedUser, setAuthenticatedUser] = useState(null)
const token = useStore(authToken)
const navigate = useNavigate()
const { pathname } = useLocation()
function isTokenExpired() {
// verify token expiration and return true or false
}
// Hook to check if user is logged in
useEffect(() => {
async function checkLogin () {
if (token) {
const expiredToken = isTokenExpired(token);
if (expiredToken) {
// clear out expired token and user from store and navigate to login page
authToken.set(null)
user.set(null)
setIsLoggedIn(false);
navigate("/login");
return;
}
}
};
checkLogin()
}, [pathname])
// Hook to fetch current user info and update state
useEffect(() => {
async function fetchUser() {
const response = await axios.get("/api/auth/user", {
headers: {
'Authorization': `Bearer ${token}`
}
})
if(response?.status !== 200) {
throw new Error("Failed to fetch user data")
}
setAuthenticatedUser(response?.data)
setIsLoggedIn(true)
}
fetchUser()
}, [])
const values = {
isLoggedIn,
authenticatedUser,
setAuthenticatedUser
}
return(
{children}
)
}
نتیجه گیری
اکنون این دو قلاب useEffect ایجاد شده در مرحله پنج، مسئول مدیریت کل وضعیت اعتبار برنامه شما هستند. هر بار که یک بهروزرسانی انجام میدهید، آنها برای بررسی توکن شما در حافظه محلی اجرا میشوند، جدیدترین دادههای کاربر را مستقیماً از باطن بازیابی میکنند و وضعیت «isLoggedIn» و «authenticatedUser» شما را بهروزرسانی میکنند. میتوانید با وارد کردن «AuthContext» و «useContext» هوک از react و فراخوانی آنها در کامپوننت خود، از حالتهای موجود در هر مؤلفه استفاده کنید تا به مقادیر دسترسی داشته باشید و از آنها برای برخی رندرهای شرطی استفاده کنید.
import { useContext } from "react";
import { AuthContext } from "./AuthContext";
export default function MyLoggedInComponent() {
const { isLoggedIn, authenticatedUser } = useContext(AuthContext)
return(
{
isLoggedIn ?
Welcome {authenticatedUser?.name}
:
}
>
)
}
به یاد داشته باشید که در هنگام خروج، باید با قرار دادن null، فروشگاه “authToken” و “user” را پاک کنید. همچنین باید «isLoggedIn» را روی false و «authenticatedUser» را روی null تنظیم کنید.
با تشکر برای خواندن!