صندوق المؤلف


ناقش مشروعك

من نحن

نحن شريك Microsoft Gold مع وجودها في جميع أنحاء الولايات المتحدة والهند. نحن مزود خدمات تقنية معلومات ديناميكي ومهني يخدم المؤسسات والشركات الناشئة ، ويساعدها على مواجهة تحديات الاقتصاد العالمي. نحن نقدم خدمات في مجال استشارات إدارة علاقات العملاء وتنفيذها ، وتطوير التطبيقات ، وتطوير تطبيقات الهاتف المحمول ، وتطوير الويب ، والتطوير الخارجي.

المصادقة في React TypeScript

كيفية تنفيذ المصادقة في React TypeScript باستخدام مصادقة JWT

By بوجا شارما / 11 مارس 2022

13 أكتوبر 2022
كيفية تنفيذ المصادقة في React TypeScript باستخدام مصادقة JWT

في هذه المقالة ، نود أن نقدم لك الطريقة الأكثر شيوعًا وحديثة لحماية تطبيق الويب الخاص بك على React Typescript أو تأمينه باستخدام مصادقة JWT. إذن ، ما هو هذا الأمان أو الحماية ولماذا نحتاج إليه.

حسنًا ، سنناقش كل هذه الأشياء في مدونتنا. لذلك ، لنبدأ:

ما هو الأمان والحماية في البرامج؟

من أجل تأمين أو حفظ البيانات ومعلومات المستخدم من مكتبة طرف ثالث غير معروفة ، هجمات XSS أو تجريف الويب أو متسلل محترف ، يمكنك استخدام بروتوكولات أمان معينة مثل HTTPS على مدى HTTP أو إجراء مصادقة في التطبيق الخاص بك أو ربما يمكنك استخدام أي طرق تشفير أمان أخرى أو طرق المجموع الاختباري حتى تظل بيانات التطبيق الخاص بك وسلامته بأمان.

لماذا نحتاج الأمن؟

حسنًا ، من أجل حماية تطبيقاتك من بعض الهجمات والمتسللين كما ذكرنا أعلاه بعض الأسباب التي تجعلنا في حاجة إليها. اسمح لي أن أشرح لك الأمر نفسه بمثال:

مثال 1:

إذا كنت تخطط للذهاب إلى محطة تل للنزهة مع جميع أفراد الأسرة ، فلماذا تغلق الأبواب والنوافذ عندما تغادر منزلك؟

لأن شخصًا ما يمكن أن يدخل منزلك إذا لم يتم قفل الأبواب والنوافذ ، أليس كذلك؟ يمكن للصوص أخذ الأشياء الثمينة ؛ يمكن لأي حيوان أن يعيد تأهيله مثل الثعبان. ولا يمكنك فعل أي شيء لأن ما مضى قد انتهى ، لأنك لم يكن لديك الأمن. يمين؟ يحمي Lock منزلك بنفس الطريقة التي يحمي بها الأمان في تطبيقات البرامج الخاصة بك.

تستخدم كل شركة تقريبًا في الوقت الحاضر الأمان أو المصادقة مثل JWT (رمز الويب JSON). إذا لم يتم تنفيذ JWT ، يمكن اختراق عدد كبير من حسابات المستخدمين بواسطة أي متسلل.

ما هو JWT أو JSON Web Token؟

رمز الويب JSON هو معيار حديث على مستوى الإنترنت لتوليد البيانات بامتداد التوقيع الطوعي والتشفير الطوعي الذي تحمل حمولته JSON التي تعلن عن عدد من المطالبات. تم التوقيع على الرموز المميزة إما باستخدام سر خاص أو مفتاح عام / خاص.

أيضا ، اقرأ: الواجهات في الكتابة المطبوعة: ما هي وكيفية استخدامها؟

كيفية تنفيذ JWT في تطبيق React TypeScript (عملية خطوة بخطوة)

الخطوات 1: إنشاء رد فعل تطبيق TypeScript على نظامك باتباع الأمر:

npx create-react-app <Any-name-you want> --template typescript

الخطوات 2:

إذهب إلى ....... الخاص بك تطبيق React Typescript الدليل وتثبيت أ ألبس الحذاء, أكسيوس, رد فعل هوك, رد الفعل المحمص & رد فعل جهاز التوجيه دوم الحزمة باتباع الأمر:  

npm install axios bootstrap [email protected] react-hook-form react-toastify

الخطوات 3:

في الخاص App.tsx ملف ، امسح كل التعليمات البرمجية و لصق الأتى. في الأساس ، ما نحاول القيام به هنا هو استيراد كل المكونات التي سننشئها في المستقبل وإضافتها رد فعل جهاز التوجيه دوم وظيفة للتوجيه إلى الصفحات التي تحتوي على روابط مختلفة ومختلفة:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.bundle.min.js";
import SignUp from "./Components/SignUp";
import Login from "./Components/Login";
import PrivateRoute from "./Auth/PrivateRoute";
import Home from "./Components/Home";
import {BrowserRouter, Route, Switch} from 'react-router-dom';
function App() {
  return (
      <BrowserRouter>
      <Switch>
        <PrivateRoute exact path="/login" component={Login}/>
        <Route exact path="/register" component={SignUp} />
        </Switch>
    </BrowserRouter>
  );
}

export default App;

الخطوات 4:

سنقوم الآن بإنشاء مسار خاص لتطبيقنا. قم بإنشاء مجلد باسم "المصادقة"وتحت هذا المجلد ، قم بإنشاء ملف جديد يُعرف باسم PrivateRoute.tsx ملف ، انسخ كل الكود والصق ما يلي ، ما نحاول القيام به هنا هو أننا نخرج رمز JWT الخاص بنا من التخزين المحلي.

وتحقق مما إذا كان لدينا رمز JWT في منطقتنا التخزين المحلي ثم سنذهب إلى مسار تسجيل الدخول ، وإلا إذا كان لديه رمز مميز ، فسيظل على الصفحة الرئيسية.

import React from "react";
import { Redirect, Route } from "react-router-dom";

const PrivateRoute = (props) => {
  const token = localStorage.getItem("auth");
  return <>{token ? <Route {...props} /> : <Redirect to="/login" />}</>;
};

export default PrivateRoute;

الخطوات 5:

الآن سنقوم بإنشاء واجهة مستخدم لهذا الغرض. اذهب أولاً إلى SRC المجلد ، ثم داخل ملف SRC إنشاء مجلد جديد باسم "المحتوى".

وداخل مجلد المكونات قم بعمل 3 ملفات على النحو التالي: 

  1. تسجيل الدخول.tsx
  2. SignUp.tsx
  3. Home.tsx
  4. home.css

قبل أن نمضي قدمًا ، تأكد من أن لديك ملكًا خاصًا بك عقدة API من مصادقة JWT التي توفر JWT Token. لأننا نستخدم الجهاز الذي تم إنشاؤه في أجهزتنا المحلية. الرجاء تغيير http://localhost:4000 URL في التعليمات البرمجية وفقًا لـ كود API URL.

في Login.tsx

import React, { FC } from "react";
import { Link } from "react-router-dom";
import { useForm } from "react-hook-form";
import axios from "axios";
import { ToastContainer, toast, Flip } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";
import { RouteComponentProps } from "react-router";

type SomeComponentProps = RouteComponentProps;
const Login: FC<SomeComponentProps> = ({ history }): JSX.Element => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const login = (data: any) => {
    let params = {
      email: data.email,
      password: data.password,
    };
    axios
      .post("http://localhost:4000/api/login", params)
      .then(function (response) {
        //   IF EMAIL ALREADY EXISTS
        if (response.data.success === false) {
          toast.error(response.data.error, {
            position: "top-right",
            autoClose: 3000,
            hideProgressBar: true,
            closeOnClick: true,
            pauseOnHover: true,
            draggable: false,
            progress: 0,
            toastId: "my_toast",
          });
        } else {
          toast.success(response.data.message, {
            position: "top-right",
            autoClose: 3000,
            hideProgressBar: true,
            closeOnClick: true,
            pauseOnHover: true,
            draggable: false,
            progress: 0,
            toastId: "my_toast",
          });
          localStorage.setItem("auth", response.data.token);
          setTimeout(() => {
            history.push("/");
          }, 3000);
        }
      })

      .catch(function (error) {
        console.log(error);
      });
  };

  return (
    <>
      <div className="container">
        <div
          className="row d-flex justify-content-center align-items-center"
          style={{ height: "100vh" }}
        >
          <div className="card mb-3" style={{ maxWidth: "320px" }}>
            <div className="col-md-12">
              <div className="card-body">
                <h3 className="card-title text-center text-secondary mt-3">
                  Login Form
                </h3>
                <form autoComplete="off" onSubmit={handleSubmit(login)}>
                  <div className="mb-3 mt-4">
                    <label className="form-label">Email</label>
                    <input
                      type="email"
                      className="form-control shadow-none"
                      id="exampleFormControlInput1"
                      {...register("email", { required: "Email is required!" })}
                    />
                    {errors.email && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.email.message}
                      </p>
                    )}
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Password</label>
                    <input
                      type="password"
                      className="form-control shadow-none"
                      id="exampleFormControlInput2"
                      {...register("password", {
                        required: "Password is required!",
                      })}
                    />
                    {errors.password && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.password.message}
                      </p>
                    )}
                  </div>
                  <div className="text-center mt-4 ">
                    <button
                      className="btn btn-outline-primary text-center shadow-none mb-3"
                      type="submit"
                    >
                      Submit
                    </button>
                    <p className="card-text pb-2">
                      Have an Account?{" "}
                      <Link style={{ textDecoration: "none" }} to={"/register"}>
                        Sign Up
                      </Link>
                    </p>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
      <ToastContainer
        position="top-right"
        autoClose={5000}
        hideProgressBar
        closeOnClick
        rtl={false}
        pauseOnFocusLoss={false}
        draggable={false}
        pauseOnHover
        limit={1}
        transition={Flip}
      />
    </>
  );
};
export default Login;

في SignUp.tsx

import React, { FC } from "react";
import { Link, RouteComponentProps } from "react-router-dom";
import { useForm } from "react-hook-form";
import axios from "axios";
import { ToastContainer, toast, Flip } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";

type SomeComponentProps = RouteComponentProps;
const SignUp: FC<SomeComponentProps> = ({ history }) => {
  const {
    register,
    handleSubmit,
    watch,
    reset,
    formState: { errors },
  } = useForm();
  const submitData = (data: any) => {
    let params = {
      firstname: data.firstname,
      lastname: data.lastname,
      email: data.email,
      password: data.password,
      confirmpassword: data.cpassword,
    };
    console.log(data);
    axios
      .post("http://localhost:4000/api/signup", params)
      .then(function (response) {
        toast.success(response.data.message, {
          position: "top-right",
          autoClose: 3000,
          hideProgressBar: true,
          closeOnClick: true,
          pauseOnHover: true,
          draggable: false,
          progress: 0,
          toastId: "my_toast",
        });
        reset();
        setTimeout(() => {
          history.push("/login");
        }, 3000);
      })

      .catch(function (error) {
        console.log(error);
      });
  };
  return (
    <>
      <div className="container">
        <div
          className="row d-flex justify-content-center align-items-center"
          style={{ height: "100vh" }}
        >
          <div className="card mb-3 mt-3 rounded" style={{ maxWidth: "500px" }}>
            <div className="col-md-12">
              <div className="card-body">
                <h3 className="card-title text-center text-secondary mt-3 mb-3">
                  Sign Up Form
                </h3>
                <form
                  className="row"
                  autoComplete="off"
                  onSubmit={handleSubmit(submitData)}
                >
                  <div className="col-md-6">
                    <div className="">
                      <label className="form-label">Firstname</label>
                      <input
                        type="text"
                        className="form-control form-control-sm"
                        id="exampleFormControlInput1"
                        {...register("firstname", {
                          required: "Firstname is required!",
                        })}
                      />
                      {errors.firstname && (
                        <p className="text-danger" style={{ fontSize: 14 }}>
                          {errors.firstname.message}
                        </p>
                      )}
                    </div>
                  </div>
                  <div className="col-md-6">
                    <div className="">
                      <label className="form-label">Lastname</label>
                      <input
                        type="text"
                        className="form-control form-control-sm"
                        id="exampleFormControlInput2"
                        {...register("lastname", {
                          required: "Lastname is required!",
                        })}
                      />
                      {errors.lastname && (
                        <p className="text-danger" style={{ fontSize: 14 }}>
                          {errors.lastname.message}
                        </p>
                      )}
                    </div>
                  </div>

                  <div className="">
                    <label className="form-label">Email</label>
                    <input
                      type="email"
                      className="form-control form-control-sm"
                      id="exampleFormControlInput3"
                      {...register("email", { required: "Email is required!" })}
                    />
                    {errors.email && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.email.message}
                      </p>
                    )}
                  </div>
                  <div className="">
                    <label className="form-label">Password</label>
                    <input
                      type="password"
                      className="form-control form-control-sm"
                      id="exampleFormControlInput5"
                      {...register("password", {
                        required: "Password is required!",
                      })}
                    />
                    {errors.password && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.password.message}
                      </p>
                    )}
                  </div>
                  <div>
                    <label className="form-label">Confirm Password</label>
                    <input
                      type="password"
                      className="form-control form-control-sm"
                      id="exampleFormControlInput6"
                      {...register("cpassword", {
                        required: "Confirm Password is required",

                        validate: (value) =>
                          value === watch("password") ||
                          "Passwords don't match.",
                      })}
                    />
                    {errors.cpassword && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.cpassword.message}
                      </p>
                    )}
                  </div>
                  <div className="text-center mt-4 ">
                    <button
                      className="btn btn-outline-primary text-center shadow-none mb-3"
                      type="submit"
                    >
                      Submit
                    </button>
                    <p className="card-text">
                      Already have an account?{" "}
                      <Link style={{ textDecoration: "none" }} to={"/login"}>
                        Log In
                      </Link>
                    </p>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
      <ToastContainer
        position="top-right"
        autoClose={5000}
        hideProgressBar
        closeOnClick
        rtl={false}
        pauseOnFocusLoss={false}
        draggable={false}
        pauseOnHover
        limit={1}
        transition={Flip}
      />
    </>
  );
};

export default SignUp;

في Home.tsx

import React, { FC } from "react";
import { RouteComponentProps } from "react-router-dom";
import "./home.css";

type SomeComponentProps = RouteComponentProps;
const Home: FC<SomeComponentProps> = ({ history }) => {
  const logout = () => {
    localStorage.clear();
    history.push("/login");
  };
  return (
    <>
      <div
        style={{
          display: "flex",
          justifyContent: "space-between",
          paddingLeft: 50,
          paddingRight: 50,
        }}
      >
        <div>
          <h3 className="m-3">Home</h3>
        </div>
        <div>
          <button type="submit" className="buttons" onClick={logout}>
            Logout
          </button>
        </div>
      </div>
      <div className="container">
        <div
          className="row d-flex justify-content-center align-items-center text-center"
          style={{ height: "100vh" }}
        >
          <p className="muted display-6">Hello User👋</p>
        </div>
      </div>
    </>
  );
};

export default Home;

في home.css

.buttons
{
    color: white;
    background: cornflowerblue;
    padding: 10px 40px;
    margin: 10px;
    border: none;
    border-radius: 30px;
    cursor: pointer;
}

أيضا ، اقرأ: كيفية استدعاء واجهة برمجة تطبيقات الويب باستخدام خطاف useEffect في React TypeScript؟

الخطوات 6:

الآن قم بتنفيذ الكود باتباع الأمر:

npm start

الخطوات 7:

الآن سترى مخرجاتك مثل هذا:

صفحة التسجيل:

صفحة تسجيل الدخول:

بعد إدخال تفاصيل تسجيل دخول صالحة ، افحص المتصفح إذا كان هناك أي رمز JWT أم لا؟ إذا كان تسجيل الدخول صالحًا ، فستبدو الشاشة على هذا النحو ، وإلا ستظهر لك رسالة كلمة مرور غير صحيحة من واجهة برمجة التطبيقات الخاصة بك.

الآن ، إذا لاحظت وجود رمز مصادقة غريب تم إنشاؤه في التطبيق 'علامة التبويب' تحت التخزين المحلي منطقة المصادقة. هذا مفتاح موقّع أو خاص مطلوب بواسطة مصادقة JWT من واجهة برمجة التطبيقات التي استخدمتها.

في حالة حذف هذا الرمز المميز من المتصفح ، فسيتم إعادة توجيهك مرة أخرى إلى صفحة تسجيل الدخول حيث لا يوجد رمز مميز متاح عليه وسيؤدي المسار الخاص دوره هنا.

مقتطف قصير من المنطق:

  1. تسجيل الدخول: في تسجيل الدخول ، أنت تقوم فقط بتمرير بيانات json للمستخدم وتحصل على رمز مميز من ملف RESTful API.
  • سجل: في التسجيل ، تقوم مرة أخرى بتمرير بيانات json للمستخدم وحفظ المستخدم في قاعدة البيانات.
  • الصفحة الرئيسية: في الصفحة الرئيسية ، تقوم بتسجيل الدخول إلى مستخدمنا باستخدام بيانات الاعتماد الصحيحة التي يقوم بإدخالها وتعيين رمز JWT الخاص بنا على المتصفح التخزين المحلي والتي تأتي من واجهة برمجة تطبيقات تسجيل الدخول.
  • تسجيل الخروج: في تسجيل الخروج ، تقوم بمسح JWT Token من ملف التخزين المحلي.

أيضا ، اقرأ: أهم تحديات تطوير الويب وحلولها

الخلاصة:

مصادقات JWT تستخدم على نطاق واسع في الوقت الحاضر ، يرجى استخدامها فقط عندما يكون ذلك مطلوبًا في مشاريعك. لا تستخدمها إذا كنت تستخدم فقط تسجيل الدخول لاستخدامك الشخصي. لأن بياناتك محلية وستكون متاحة لك فقط ، لذلك لا فائدة من استخدامها للاستخدام الشخصي. لكن نعم ، إنها طريقة قوية جدًا وقوية وآمنة لنقل بياناتك.

توفر الكود:

https://github.com/Akshay80/React-TS-login-using-jwt/tree/main/src/Auth

شكرا جزيلا لقراءتك هذه المدونة بصبر 😊، 

أتمنى لك يومًا سعيدًا 👋.

[sc name = "تطوير الويب"] [add_newsletter] [add_related_page_diff_contents blog_cat = "تطبيق ويب"]

في هذه المقالة ، نود أن نقدم لك الطريقة الأكثر شيوعًا وحديثة لحماية تطبيق الويب الخاص بك على React Typescript أو تأمينه باستخدام مصادقة JWT. إذن ، ما هو هذا الأمان أو الحماية ولماذا نحتاج إليه.

حسنًا ، سنناقش كل هذه الأشياء في مدونتنا. لذلك ، لنبدأ:

ما هو الأمان والحماية في البرامج؟

من أجل تأمين أو حفظ البيانات ومعلومات المستخدم من مكتبة طرف ثالث غير معروفة ، هجمات XSS أو تجريف الويب أو متسلل محترف ، يمكنك استخدام بروتوكولات أمان معينة مثل HTTPS على مدى HTTP أو إجراء مصادقة في التطبيق الخاص بك أو ربما يمكنك استخدام أي طرق تشفير أمان أخرى أو طرق المجموع الاختباري حتى تظل بيانات التطبيق الخاص بك وسلامته بأمان.

لماذا نحتاج الأمن؟

حسنًا ، من أجل حماية تطبيقاتك من بعض الهجمات والمتسللين كما ذكرنا أعلاه بعض الأسباب التي تجعلنا في حاجة إليها. اسمح لي أن أشرح لك الأمر نفسه بمثال:

مثال 1:

إذا كنت تخطط للذهاب إلى محطة تل للنزهة مع جميع أفراد الأسرة ، فلماذا تغلق الأبواب والنوافذ عندما تغادر منزلك؟

لأن شخصًا ما يمكن أن يدخل منزلك إذا لم يتم قفل الأبواب والنوافذ ، أليس كذلك؟ يمكن للصوص أخذ الأشياء الثمينة ؛ يمكن لأي حيوان أن يعيد تأهيله مثل الثعبان. ولا يمكنك فعل أي شيء لأن ما مضى قد انتهى ، لأنك لم يكن لديك الأمن. يمين؟ يحمي Lock منزلك بنفس الطريقة التي يحمي بها الأمان في تطبيقات البرامج الخاصة بك.

تستخدم كل شركة تقريبًا في الوقت الحاضر الأمان أو المصادقة مثل JWT (رمز الويب JSON). إذا لم يتم تنفيذ JWT ، يمكن اختراق عدد كبير من حسابات المستخدمين بواسطة أي متسلل.

ما هو JWT أو JSON Web Token؟

رمز الويب JSON هو معيار حديث على مستوى الإنترنت لتوليد البيانات بامتداد التوقيع الطوعي والتشفير الطوعي الذي تحمل حمولته JSON التي تعلن عن عدد من المطالبات. تم التوقيع على الرموز المميزة إما باستخدام سر خاص أو مفتاح عام / خاص.

أيضا ، اقرأ: الواجهات في الكتابة المطبوعة: ما هي وكيفية استخدامها؟

كيفية تنفيذ JWT في تطبيق React TypeScript (عملية خطوة بخطوة)

الخطوات 1: إنشاء رد فعل تطبيق TypeScript على نظامك باتباع الأمر:

npx create-react-app <Any-name-you want> --template typescript

الخطوات 2:

إذهب إلى ....... الخاص بك تطبيق React Typescript الدليل وتثبيت أ ألبس الحذاء, أكسيوس, رد فعل هوك, رد الفعل المحمص & رد فعل جهاز التوجيه دوم الحزمة باتباع الأمر:  

npm install axios bootstrap [email protected] react-hook-form react-toastify

الخطوات 3:

في الخاص App.tsx ملف ، امسح كل التعليمات البرمجية و لصق الأتى. في الأساس ، ما نحاول القيام به هنا هو استيراد كل المكونات التي سننشئها في المستقبل وإضافتها رد فعل جهاز التوجيه دوم وظيفة للتوجيه إلى الصفحات التي تحتوي على روابط مختلفة ومختلفة:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.bundle.min.js";
import SignUp from "./Components/SignUp";
import Login from "./Components/Login";
import PrivateRoute from "./Auth/PrivateRoute";
import Home from "./Components/Home";
import {BrowserRouter, Route, Switch} from 'react-router-dom';
function App() {
  return (
      <BrowserRouter>
      <Switch>
        <PrivateRoute exact path="/login" component={Login}/>
        <Route exact path="/register" component={SignUp} />
        </Switch>
    </BrowserRouter>
  );
}

export default App;

الخطوات 4:

سنقوم الآن بإنشاء مسار خاص لتطبيقنا. قم بإنشاء مجلد باسم "المصادقة"وتحت هذا المجلد ، قم بإنشاء ملف جديد يُعرف باسم PrivateRoute.tsx ملف ، انسخ كل الكود والصق ما يلي ، ما نحاول القيام به هنا هو أننا نخرج رمز JWT الخاص بنا من التخزين المحلي.

وتحقق مما إذا كان لدينا رمز JWT في منطقتنا التخزين المحلي ثم سنذهب إلى مسار تسجيل الدخول ، وإلا إذا كان لديه رمز مميز ، فسيظل على الصفحة الرئيسية.

import React from "react";
import { Redirect, Route } from "react-router-dom";

const PrivateRoute = (props) => {
  const token = localStorage.getItem("auth");
  return <>{token ? <Route {...props} /> : <Redirect to="/login" />}</>;
};

export default PrivateRoute;

الخطوات 5:

الآن سنقوم بإنشاء واجهة مستخدم لهذا الغرض. اذهب أولاً إلى SRC المجلد ، ثم داخل ملف SRC إنشاء مجلد جديد باسم "المحتوى".

وداخل مجلد المكونات قم بعمل 3 ملفات على النحو التالي: 

  1. تسجيل الدخول.tsx
  2. SignUp.tsx
  3. Home.tsx
  4. home.css

قبل أن نمضي قدمًا ، تأكد من أن لديك ملكًا خاصًا بك عقدة API من مصادقة JWT التي توفر JWT Token. لأننا نستخدم الجهاز الذي تم إنشاؤه في أجهزتنا المحلية. الرجاء تغيير http://localhost:4000 URL في التعليمات البرمجية وفقًا لـ كود API URL.

في Login.tsx

import React, { FC } from "react";
import { Link } from "react-router-dom";
import { useForm } from "react-hook-form";
import axios from "axios";
import { ToastContainer, toast, Flip } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";
import { RouteComponentProps } from "react-router";

type SomeComponentProps = RouteComponentProps;
const Login: FC<SomeComponentProps> = ({ history }): JSX.Element => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const login = (data: any) => {
    let params = {
      email: data.email,
      password: data.password,
    };
    axios
      .post("http://localhost:4000/api/login", params)
      .then(function (response) {
        //   IF EMAIL ALREADY EXISTS
        if (response.data.success === false) {
          toast.error(response.data.error, {
            position: "top-right",
            autoClose: 3000,
            hideProgressBar: true,
            closeOnClick: true,
            pauseOnHover: true,
            draggable: false,
            progress: 0,
            toastId: "my_toast",
          });
        } else {
          toast.success(response.data.message, {
            position: "top-right",
            autoClose: 3000,
            hideProgressBar: true,
            closeOnClick: true,
            pauseOnHover: true,
            draggable: false,
            progress: 0,
            toastId: "my_toast",
          });
          localStorage.setItem("auth", response.data.token);
          setTimeout(() => {
            history.push("/");
          }, 3000);
        }
      })

      .catch(function (error) {
        console.log(error);
      });
  };

  return (
    <>
      <div className="container">
        <div
          className="row d-flex justify-content-center align-items-center"
          style={{ height: "100vh" }}
        >
          <div className="card mb-3" style={{ maxWidth: "320px" }}>
            <div className="col-md-12">
              <div className="card-body">
                <h3 className="card-title text-center text-secondary mt-3">
                  Login Form
                </h3>
                <form autoComplete="off" onSubmit={handleSubmit(login)}>
                  <div className="mb-3 mt-4">
                    <label className="form-label">Email</label>
                    <input
                      type="email"
                      className="form-control shadow-none"
                      id="exampleFormControlInput1"
                      {...register("email", { required: "Email is required!" })}
                    />
                    {errors.email && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.email.message}
                      </p>
                    )}
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Password</label>
                    <input
                      type="password"
                      className="form-control shadow-none"
                      id="exampleFormControlInput2"
                      {...register("password", {
                        required: "Password is required!",
                      })}
                    />
                    {errors.password && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.password.message}
                      </p>
                    )}
                  </div>
                  <div className="text-center mt-4 ">
                    <button
                      className="btn btn-outline-primary text-center shadow-none mb-3"
                      type="submit"
                    >
                      Submit
                    </button>
                    <p className="card-text pb-2">
                      Have an Account?{" "}
                      <Link style={{ textDecoration: "none" }} to={"/register"}>
                        Sign Up
                      </Link>
                    </p>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
      <ToastContainer
        position="top-right"
        autoClose={5000}
        hideProgressBar
        closeOnClick
        rtl={false}
        pauseOnFocusLoss={false}
        draggable={false}
        pauseOnHover
        limit={1}
        transition={Flip}
      />
    </>
  );
};
export default Login;

في SignUp.tsx

import React, { FC } from "react";
import { Link, RouteComponentProps } from "react-router-dom";
import { useForm } from "react-hook-form";
import axios from "axios";
import { ToastContainer, toast, Flip } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";

type SomeComponentProps = RouteComponentProps;
const SignUp: FC<SomeComponentProps> = ({ history }) => {
  const {
    register,
    handleSubmit,
    watch,
    reset,
    formState: { errors },
  } = useForm();
  const submitData = (data: any) => {
    let params = {
      firstname: data.firstname,
      lastname: data.lastname,
      email: data.email,
      password: data.password,
      confirmpassword: data.cpassword,
    };
    console.log(data);
    axios
      .post("http://localhost:4000/api/signup", params)
      .then(function (response) {
        toast.success(response.data.message, {
          position: "top-right",
          autoClose: 3000,
          hideProgressBar: true,
          closeOnClick: true,
          pauseOnHover: true,
          draggable: false,
          progress: 0,
          toastId: "my_toast",
        });
        reset();
        setTimeout(() => {
          history.push("/login");
        }, 3000);
      })

      .catch(function (error) {
        console.log(error);
      });
  };
  return (
    <>
      <div className="container">
        <div
          className="row d-flex justify-content-center align-items-center"
          style={{ height: "100vh" }}
        >
          <div className="card mb-3 mt-3 rounded" style={{ maxWidth: "500px" }}>
            <div className="col-md-12">
              <div className="card-body">
                <h3 className="card-title text-center text-secondary mt-3 mb-3">
                  Sign Up Form
                </h3>
                <form
                  className="row"
                  autoComplete="off"
                  onSubmit={handleSubmit(submitData)}
                >
                  <div className="col-md-6">
                    <div className="">
                      <label className="form-label">Firstname</label>
                      <input
                        type="text"
                        className="form-control form-control-sm"
                        id="exampleFormControlInput1"
                        {...register("firstname", {
                          required: "Firstname is required!",
                        })}
                      />
                      {errors.firstname && (
                        <p className="text-danger" style={{ fontSize: 14 }}>
                          {errors.firstname.message}
                        </p>
                      )}
                    </div>
                  </div>
                  <div className="col-md-6">
                    <div className="">
                      <label className="form-label">Lastname</label>
                      <input
                        type="text"
                        className="form-control form-control-sm"
                        id="exampleFormControlInput2"
                        {...register("lastname", {
                          required: "Lastname is required!",
                        })}
                      />
                      {errors.lastname && (
                        <p className="text-danger" style={{ fontSize: 14 }}>
                          {errors.lastname.message}
                        </p>
                      )}
                    </div>
                  </div>

                  <div className="">
                    <label className="form-label">Email</label>
                    <input
                      type="email"
                      className="form-control form-control-sm"
                      id="exampleFormControlInput3"
                      {...register("email", { required: "Email is required!" })}
                    />
                    {errors.email && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.email.message}
                      </p>
                    )}
                  </div>
                  <div className="">
                    <label className="form-label">Password</label>
                    <input
                      type="password"
                      className="form-control form-control-sm"
                      id="exampleFormControlInput5"
                      {...register("password", {
                        required: "Password is required!",
                      })}
                    />
                    {errors.password && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.password.message}
                      </p>
                    )}
                  </div>
                  <div>
                    <label className="form-label">Confirm Password</label>
                    <input
                      type="password"
                      className="form-control form-control-sm"
                      id="exampleFormControlInput6"
                      {...register("cpassword", {
                        required: "Confirm Password is required",

                        validate: (value) =>
                          value === watch("password") ||
                          "Passwords don't match.",
                      })}
                    />
                    {errors.cpassword && (
                      <p className="text-danger" style={{ fontSize: 14 }}>
                        {errors.cpassword.message}
                      </p>
                    )}
                  </div>
                  <div className="text-center mt-4 ">
                    <button
                      className="btn btn-outline-primary text-center shadow-none mb-3"
                      type="submit"
                    >
                      Submit
                    </button>
                    <p className="card-text">
                      Already have an account?{" "}
                      <Link style={{ textDecoration: "none" }} to={"/login"}>
                        Log In
                      </Link>
                    </p>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
      <ToastContainer
        position="top-right"
        autoClose={5000}
        hideProgressBar
        closeOnClick
        rtl={false}
        pauseOnFocusLoss={false}
        draggable={false}
        pauseOnHover
        limit={1}
        transition={Flip}
      />
    </>
  );
};

export default SignUp;

في Home.tsx

import React, { FC } from "react";
import { RouteComponentProps } from "react-router-dom";
import "./home.css";

type SomeComponentProps = RouteComponentProps;
const Home: FC<SomeComponentProps> = ({ history }) => {
  const logout = () => {
    localStorage.clear();
    history.push("/login");
  };
  return (
    <>
      <div
        style={{
          display: "flex",
          justifyContent: "space-between",
          paddingLeft: 50,
          paddingRight: 50,
        }}
      >
        <div>
          <h3 className="m-3">Home</h3>
        </div>
        <div>
          <button type="submit" className="buttons" onClick={logout}>
            Logout
          </button>
        </div>
      </div>
      <div className="container">
        <div
          className="row d-flex justify-content-center align-items-center text-center"
          style={{ height: "100vh" }}
        >
          <p className="muted display-6">Hello User👋</p>
        </div>
      </div>
    </>
  );
};

export default Home;

في home.css

.buttons
{
    color: white;
    background: cornflowerblue;
    padding: 10px 40px;
    margin: 10px;
    border: none;
    border-radius: 30px;
    cursor: pointer;
}

أيضا ، اقرأ: كيفية استدعاء واجهة برمجة تطبيقات الويب باستخدام خطاف useEffect في React TypeScript؟

الخطوات 6:

الآن قم بتنفيذ الكود باتباع الأمر:

npm start

الخطوات 7:

الآن سترى مخرجاتك مثل هذا:

صفحة التسجيل:

صفحة تسجيل الدخول:

بعد إدخال تفاصيل تسجيل دخول صالحة ، افحص المتصفح إذا كان هناك أي رمز JWT أم لا؟ إذا كان تسجيل الدخول صالحًا ، فستبدو الشاشة على هذا النحو ، وإلا ستظهر لك رسالة كلمة مرور غير صحيحة من واجهة برمجة التطبيقات الخاصة بك.

الآن ، إذا لاحظت وجود رمز مصادقة غريب تم إنشاؤه في التطبيق 'علامة التبويب' تحت التخزين المحلي منطقة المصادقة. هذا مفتاح موقّع أو خاص مطلوب بواسطة مصادقة JWT من واجهة برمجة التطبيقات التي استخدمتها.

في حالة حذف هذا الرمز المميز من المتصفح ، فسيتم إعادة توجيهك مرة أخرى إلى صفحة تسجيل الدخول حيث لا يوجد رمز مميز متاح عليه وسيؤدي المسار الخاص دوره هنا.

مقتطف قصير من المنطق:

  1. تسجيل الدخول: في تسجيل الدخول ، أنت تقوم فقط بتمرير بيانات json للمستخدم وتحصل على رمز مميز من ملف RESTful API.
  • سجل: في التسجيل ، تقوم مرة أخرى بتمرير بيانات json للمستخدم وحفظ المستخدم في قاعدة البيانات.
  • الصفحة الرئيسية: في الصفحة الرئيسية ، تقوم بتسجيل الدخول إلى مستخدمنا باستخدام بيانات الاعتماد الصحيحة التي يقوم بإدخالها وتعيين رمز JWT الخاص بنا على المتصفح التخزين المحلي والتي تأتي من واجهة برمجة تطبيقات تسجيل الدخول.
  • تسجيل الخروج: في تسجيل الخروج ، تقوم بمسح JWT Token من ملف التخزين المحلي.

أيضا ، اقرأ: أهم تحديات تطوير الويب وحلولها

الخلاصة:

مصادقات JWT تستخدم على نطاق واسع في الوقت الحاضر ، يرجى استخدامها فقط عندما يكون ذلك مطلوبًا في مشاريعك. لا تستخدمها إذا كنت تستخدم فقط تسجيل الدخول لاستخدامك الشخصي. لأن بياناتك محلية وستكون متاحة لك فقط ، لذلك لا فائدة من استخدامها للاستخدام الشخصي. لكن نعم ، إنها طريقة قوية جدًا وقوية وآمنة لنقل بياناتك.

توفر الكود:

https://github.com/Akshay80/React-TS-login-using-jwt/tree/main/src/Auth

شكرا جزيلا لقراءتك هذه المدونة بصبر 😊، 

أتمنى لك يومًا سعيدًا 👋.

خدمات تطوير الويب

هل تبحث عن شركة تطوير ويب موثوقة؟ يمكّننا مطورو الويب ذوو المهارات العالية لدينا من تقديم خدمات تطوير الويب الموجهة نحو النتائج. اتصل بفريقنا لفهم كيف يمكننا مساعدتك في تحقيق أهداف عملك.



ضيف
0 التعليقات
التقيمات المضمنة
عرض جميع التعليقات
0
أحب أفكارك ، يرجى التعليق.x
()
x