احراز هویت در ری اکت یکی از مهمترین مفاهیمی هست که هر توسعه دهنده React باید بهش مسلط باشه و به بهترین شکل ممکن اون رو پیاده سازی کنه. تو این مقاله میخوایم مفهوم Authorization و Authentication در ری اکت رو بررسی کنیم.
ما باید از کاربران خودمون نام کاربری و پسورد بگیریم و اگه اطلاعاتشون درست بود، به صفحاتی مثل داشبورد منتقلشون کنیم.
همچنین باید از ورود کاربران احراز نشده به برخی صفحات جلوگیری کنیم. ( یعنی گارد در ری اکت )
تو این مقاله میخوایم بهترین و حرفه ای ترین روش احراز هویت در React رو باهمدیگه بررسی کنیم و یاد بگیریم 🙂
برای اینکه بتونیم مبحث Authentication در React رو یادبگیریم، لازمه یک پروژه ری اکتی ایجاد کنیم تا این مبحث رو بصورت عملی باهمدیگه بررسی کنیم. با دستور زیر میتونیم یک پروژه ری اکتی ایجاد کنیم :
npm create vite@latest your-project-name -- --template react
و سپس به کمک دستور زیر میتونیم پروژه خودمون رو اجرا کنیم :
npm run dev
ما میخوایم یک کامپوننت به اسم Login درست کنیم که پروسه ورود کاربران رو انجام میده. این کامپوننت شامل دو Input ( یک فیلد ایمیل و یک فیلد پسورد ) میشه.
زمانیکه کاربر email و password خودش رو وارد میکنه، اطلاعات وارد شده داخل State تعریف شده در خط 5 ذخیره میشه.
سپس زمانیکه کاربر روی دکمه “ورود” کلیک میکنه، تابع handleSubmitEvent اجرا میشه.
import { Button, Input } from "antd"
import { useState } from "react"
const Login = () => {
const [input, setInput] = useState({
username: "",
password: "",
});
const handleSubmitEvent = (e) => {
e.preventDefault();
if (input.username !== "" && input.password !== "") {
//dispatch action from hooks
}
alert("please provide a valid input");
};
const handleInput = (e) => {
const { name, value } = e.target;
setInput((prev) => ({
...prev,
[name]: value,
}));
};
return (
<form ={handleSubmitEvent} style={{direction:'rtl',display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center'}}>
<div className="form_control">
<label htmlFor="user-email">ایمیل:</label>
<Input
style={{width:'200px'}}
type="email"
id="user-email"
name="email"
placeholder="FrontEndi.com@gmail.com"
aria-describedby="user-email"
aria-invalid="false"
={handleInput}
/>
</div>
<div className="form_control">
<label htmlFor="password">پسورد:</label>
<Input
style={{width:'200px'}}
type="password"
id="password"
name="password"
aria-describedby="user-password"
aria-invalid="false"
={handleInput}
/>
</div>
<Button className="btn-submit">ورود</Button>
</form>
);
};
export default Login;
تو کامپوننت بالا من از کتابخانه Antd استفاده کردم اما شما میتونید ازش استفاده نکنید ضمنا اگه علاقه داشتید میتونید از آموزش کتابخانه Ant Design برای یادگیری این کتابخونه مفید و قدرتمند استفاده کنید. خروجی کامپوننت بالا بصورت زیر هست :
ما از Context API برای این استفاده میکنیم که به یکسری State گلوبال که تو کل اپیکیشن بهشون نیاز داریم، دسترسی داشته باشیم. در حقیقت ما نیاز داریم که اطلاعات کاربر احراز شده رو در یک State گلوبال ذخیره کنیم و از کل اپیکیشن بهش دسترسی داشته باشیم.
اگه با خود Context آشنا نیستید، حتما پیشنهاد میکنم مقاله useContext در ری اکت رو مطالعه کنید.
ما میخوایم اطلاعات کاربر احراز شده ( Login شده ) رو ذخیره کنیم و در کامپوننت ها و صفحات مختلف بهش دسترسی داشته باشیم. حالا شاید بپرسیم چرا دسترسی داشته باشیم؟
مثلا تو کامپوننت هدر میخوایم نام و میزان موجودی کیف پول کاربر رو نشون بدیم یا تو برخی صفحات چک کنیم که کاربر وارد شده کی هست و اگه وارد نشده بود، کاربر رو logout کنیم.
برای اینکار من یک فایل به اسم AuthProvider.js میسازم و داخلش یک Context به اسم AuthContext درست میکنم :
import { useContext, createContext } from "react"
const AuthContext = createContext();
const AuthProvider = ({ children }) => {
return <AuthContext.Provider>{children}</AuthContext.Provider>;
};
export default AuthProvider;
export const useAuth = () => {
return useContext(AuthContext);
};
تو خط 2 تیکه کد بالا من یک Context ساختم. تو خط 10 نیز یک Custom Hook ساختم که بتونم از این Context خیلی راحت تر استفاده کنم و پروسه احراز هویت کاربر برای ما آسون تر مدیریت بشه.
تو خط 4 تیکه کد بالا ما AuthProvider رو ساختیم تا کل اپیکیشن خودمون رو داخل این HOC بندازیم. اینجوری تمام صفحات و کامپوننت های ما از این Logic استفاده میکنن ( منظورم Logic احراز هویت هست )
البته تیکه کد بالا کامل نیست و در ادامه کاملترش میکنم.
حالا باید AuthProvider خودمون که ساختیم رو دور کل اپیکیشن خودمون بندازیم، یعنی وارد فایل App.js یا main.js خودمون بشیم و بصورت زیر عمل کنیم :
حالا Logic ما ( احراز هویت در ری اکت ) تو کل اپیکیشن ری اکتی ما قابل استفادس!
اما ما هیچ تابعی برای مدیریت پروسه Login و Logout ( ورود و خروج کاربر ) نداریم!
برای تکمیل پروسه احراز هویت در ری اکت لازمه که 2 تابع برای ورود و خروج کاربر ایجاد کنیم. برای اینکار وارد فایل AuthProvider میشیم و این 2 تابع رو ایجاد میکنیم :
import { useContext, createContext, useState } from "react"
import { useNavigate } from "react-router-dom"
const AuthContext = createContext();
const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [token, setToken] = useState(localStorage.getItem("site") || "");
const navigate = useNavigate();
const loginAction = async (data) => {
try {
const response = await fetch("your-api-endpoint/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
const res = await response.json();
if (res.data) {
setUser(res.data.user);
setToken(res.token);
localStorage.setItem("site", res.token);
navigate("/dashboard");
return;
}
throw new Error(res.message);
} catch (err) {
console.error(err);
}
};
const logOut = () => {
setUser(null);
setToken("");
localStorage.removeItem("site");
navigate("/login");
};
return (
<AuthContext.Provider value={{ token, user, loginAction, logOut }}>
{children}
</AuthContext.Provider>
);
};
export default AuthProvider;
export const useAuth = () => {
return useContext(AuthContext);
};
تو خط 10 ما تابع loginAction رو ساختیم و میخوایم این تابع رو در صفحه Login زمانیکه کاربر نام کاربری و پسورد خودش رو وارد کرد صدا بزنیم. این تابع یک data به عنوان آرگومان ورودی میگیره.
این data همون نام کاربری و پسوردی هست که کاربر در صفحه ورود وارد میکنه.
تو خط 12 ما API خودمون که مرتبط با Login هست رو صدا میزنیم ( POST ) و نام کاربری و پسورد وارد شده توسط کاربر رو به API میفرستیم. سرور این اطلاعات رو بررسی میکنه ببینه درست هستن یا خیر.
اگر اطلاعات وارد شده توسط کاربر صحیح بود، در Response برای ما یک token و اطلاعات کاربر احراز شده رو میفرسته.
ما این اطلاعات رو در خط 21 و 22 داخل State خودمون ذخیره میکنیم. همچنین در خط 23 این اطلاعات رو داخل localstorage ذخیره میکنیم تا با رفرش شدن صفحه پاک نشن.
تو خط 24 هم کاربر احراز هویت شده رو به آدرس dashboard/ ریدایرکت میکنیم.
همچنین تو خط 33 تابع logOut رو ساختیم که پروسه خروج کاربر رو مدیریت میکنه. این تابع اطلاعات کاربر داخل State و localstorage رو پاک میکنه و کاربر رو به صفحه login/ ریدایرکت میکنه.
و این عالیه 🙂
الان دیگه هرموقع نیاز داشتیم میتونیم از تابع loginAction برای ورود کاربر و از تابع logOut برای خروج کاربر تو اپیکیشن خودمون استفاده کنیم، اما این تمام ماجرای احراز هویت در React نیست!
ما تو پروژه ری اکتی خودمون Route های خیلی زیادی داریم که باید ازشون محافظت کنیم ( Protecting Routes )
منظورم از محافظت این هست به کاربرانی که احراز هویت نشدن، اجازه نمایش اون صفحات رو ندیم!
در حقیقت ما باید یک Guard ( گارد ) بسازیم. برای اینکار من یک کامپوننت به اسم PrivateRoute میسازم.
لطفا برای مطالعه ادامه آموزش Authentication در react روی لینک زیر کلیک کنید :