如何使用Node,Express,Typescript实现JWT身份验证? 2023
#网络开发人员 #typescript #node #express

今天,我们将学习如何使用JWT,Express,Typescript。

目录

  • 什么是JSON Web令牌(JWT)
  • 初始化项目
  • 安装依赖关系和DevDecondies
  • 带有打字稿的设置Express Server
  • 创建用户模型
  • 创建用户API注册
  • 板条板登录API并实现JWT身份验证

1.什么是JSON Web令牌(JWT)

JSON Web令牌(JWT)是JSON对象,用于通过Web(两方之间)安全地传输信息。它通常用于身份验证系统,也可用于信息交换。

这用于通过Internet通过Internet进行加密传输数据,这些令牌可以通过使用其他签名来保护这些令牌。

2.初始化项目

mkdir jwt-authentication
cd jwt-authentication
npm init --yes

3.安装依赖性和Dev依赖性

3.1安装依赖项

npm install express mongoose cors jsonwebtoken dotenv

3.2安装devDentipencies

npm install -D typescript nodemon @types/express @types/cors @types/jsonwebtoken

3.3添加tsconfig.json用于打字稿配置

tsc --init
  • 在tsconfig.json文件中添加此cofig
{
    "compilerOptions": {
        /* Language and Environment */
        "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
        /* Modules */
        "module": "commonjs" /* Specify what module code is generated. */,
        "rootDir": "./",
        "outDir": "./dist",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,

        /* Type Checking */
        "strict": true,
        "skipLibCheck": true /* Skip type checking all .d.ts files. */
    }
}

4.用打字稿设置Express Server

在根中创建一个文件名app.ts

folder_structure

import express from "express";
import { Application } from "express";
import mongoose from "mongoose";
import cors from "cors";
import dotenv from "dotenv";
// Create the express app and  import the type of app from express;
const app: Application = express();

// Cors
app.use(cors());
//configure env;
dotenv.config();
// Parser
app.use(express.json());
app.use(
  express.urlencoded({
    extended: true,
  })
);
// Declare The PORT Like This
const PORT: number = 8000;

app.get("/", (req, res) => {
  res.send("<h1>Welcome To JWT Authentication </h1>");
});

// Listen the server
app.listen(PORT, async () => {
  console.log(`🗄️  Server Fire on http:localhost//${PORT}`);

  // Connect To The Database
  try {
    await mongoose.connect(
      process.env.DATABASE_URL as string
    );
    console.log("🛢️  Connected To Database");
  } catch (error) {
    console.log("⚠️ Error to connect Database");
  }
});

在软件包中。json添加此srcipt

"scripts": {
    "dev": "nodemon app.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

更新软件包。JSON文件打开终端并运行命令

npm run dev

在终端中您会看到

Termail_image

打开浏览器并键入URL“ http://localhost:8000

browser_image

Express Server现在正在启动并运行!

5.创建用户模型

使用Mongoose软件包创建用户模型。该模型代表数据库中的每个用户。

在根中创建模型文件夹,创建文件用户。

user_model

uners user.ts创建用户架构;

import mongoose from "mongoose";

const UserSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true,
    },
    email: {
      type: String,
      unique: true,
      required: true,
    },
    password: {
      type: String,
      required: true,
    },
  },
  { timestamps: true }
);

export const User = mongoose.model("Users", UserSchema);

创建用户模型后,我们准备实现JWT身份验证。

6.创建用户API注册

在“ app.ts”中创建一个寄存器API以创建帐户。
api ='/auth/寄存器'

app.post("/auth/register", async (req, res) => {
  try {
    // ** Get The User Data From Body ;
    const user = req.body;

    // ** destructure the information from user;
    const { name, email, password } = user;

    // ** Check the email all ready exist  in database or not ;
    // ** Import the user model from "./models/user";

    const isEmailAllReadyExist = await User.findOne({
      email: email,
    });

    // ** Add a condition if the user exist we will send the response as email all ready exist
    if (isEmailAllReadyExist) {
      res.status(400).json({
        status: 400,
        message: "Email all ready in use",
      });
       return;
    }

    // ** if not create a new user ;
    // !! Don't save the password as plain text in db . I am saving just for demonstration.
    // ** You can use bcrypt to hash the plain password.

    // now create the user;
    const newUser = await User.create({
      name,
      email,
      password,
    });

    // Send the newUser as  response;
    res.status(200).json({
      status: 201,
      success: true,
      message: " User created Successfully",
      user: newUser,
    });
  } catch (error: any) {
    // console the error to debug
    console.log(error);

    // Send the error message to the client
    res.status(400).json({
      status: 400,
      message: error.message.toString(),
    });
  }
});

现在测试API。我正在使用vs代码市场中可用的雷电扩展。

如果一切正常

register_api_test

现在,如果我尝试通过相同的电子邮件创建相同的用户,它将向我发送错误消息。

register_aapi_eror_message

创建用户后,我们可以启动JWT实施。

7.板条板登录API并实现JWT身份验证

api ='/auth/login'

  • 从身体获取用户数据。
  • 破坏用户的信息。
  • 检查(电子邮件/用户)是否存在于数据库中。
  • 如果没有任何用户,我们找不到电子邮件。
  • 如果(用户)存在于数据库中,我们将检查密码是否有效。
  • 比较数据库中的密码和请求主体中的密码。
  • 如果不匹配,请发送错误的密码。
  • 如果电子邮件和密码有效创建令牌。
  • 创建一个令牌jsonwebtoken(JWT)接收3个参数

    1. 有效载荷 - 其中包含要在令牌中包含的索赔或数据。
    2. 秘密密钥 - 仅用于签名令牌的服务器已知的安全键。
    3. 到期 - 其他设置,例如令牌到期或算法选择。
  • 不要公开提供秘密,此秘密对服务器非常敏感。将其保存在.env文件中。我只是为了演示而保持开放。

  • 创建令牌发送响应后。

app.post("/auth/login", async (req, res) => {
  try {
    // ** Get The User Data From Body ;
    const user = req.body;

    // ** destructure the information from user;
    const { email, password } = user;

    // ** Check the (email/user) exist  in database or not ;
    const isUserExist = await User.findOne({
      email: email,
    });

    // ** if there is not any user we will send user not found;
    if (!isUserExist) {
      res.status(404).json({
        status: 404,
        success: false,
        message: "User not found",
      });
return;
    }

    // ** if the (user) exist  in database we will check the password is valid or not ;
    // **  compare the password in db and the password sended in the request body

    const isPasswordMatched =
      isUserExist?.password === password;

    // ** if not matched send response that wrong password;

    if (!isPasswordMatched) {
      res.status(400).json({
        status: 400,
        success: false,
        message: "wrong password",
      });
        return;
    }

    // ** if the email and password is valid create a token

    /*
    To create a token JsonWebToken (JWT) receive's 3 parameter
    1. Payload -  This contains the claims or data you want to include in the token.
    2. Secret Key - A secure key known only to the server used for signing the token.
    3. expiration -  Additional settings like token expiration or algorithm selection.
    */

    // !! Don't Provide the secret openly, keep it in the .env file. I am Keeping Open just for demonstration

    // ** This is our JWT Token
    const token = jwt.sign(
      { _id: isUserExist?._id, email: isUserExist?.email },
      "YOUR_SECRET",
      {
        expiresIn: "1d",
      }
    );

    // send the response
    res.status(200).json({
      status: 200,
      success: true,
      message: "login success",
      token: token,
    });
  } catch (error: any) {
    // Send the error message to the client
    res.status(400).json({
      status: 400,
      message: error.message.toString(),
    });
  }
});

现在测试API。我正在使用vs代码市场中可用的雷电扩展。

现在,如果尝试使用错误的电子邮件登录,它将发送未找到的用户错误

login_wrong_email_response

现在,如果尝试使用正确的电子邮件登录,但是错误的密码将发送错误的密码错误。

login_wrong_password_response

如果我提供了正确的电子邮件和密码,它将向我发送我们创建的令牌。

login_seccess_response

现在,如果我们复制登录后获得的令牌,然后转到https://jwt.io/并经过令牌并按DECODE

我们可以看到我们提供的有关创建时间的信息。

json_decode

如果您发现这个帮助,请给星星
也与他人分享。

github repo:https://github.com/CrisTain333/jwt-authentication-node-express-typescript

就是这样。