JWT(Json 웹 토큰)를 사용한 Node.js API 인증 - 인증 미들웨어

안녕하세요, 오늘은 node.js 어플리케이션에서 JWT로 API 인증을 구현할 예정입니다. 인증은 모든 애플리케이션에서 가장 중요한 기능입니다. 초보자라도 이 튜토리얼을 자유롭게 시도해 보십시오. 처음부터 시작하겠습니다. 또한 인증된 사람만 경로에 액세스할 수 있도록 하는 Auth 미들웨어를 작성할 것입니다.

더 나은 이해를 위해 데모 비디오 보기

Source Code

코딩을 시작하자...

앱 개요:

프로젝트 구조

다음 표는 내보낼 Rest API의 개요를 보여줍니다.


행동 양식
URL
행위


게시하다
/api/사용자
사용자 만들기

게시하다
/api/인증
사용자 인증

가져 오기
/api/사용자/me
인증된 사용자 세부 정보 가져오기


Node.js 앱 만들기 및 종속성 설치

$    mkdir node-auth-jwt
$    cd node-auth-jwt
$    npm init --yes
$    npm install express mongoose jsonwebtoken bcrypt joi dotenv


express : Express는 최소한의 유연한 Node.js 웹 애플리케이션 프레임워크입니다.
mongoose : Mongoose는 MongoDB 및 Node.js용 객체 데이터 모델링(ODM) 라이브러리입니다.
jsonwebtoken : 두 당사자 간에 전송될 클레임을 나타내는 압축 URL입니다.
bcrypt : 비밀번호 해싱 기능입니다.
joi : Joi는 자바스크립트 개체에 대한 개체 스키마 설명 언어 및 유효성 검사기입니다.
dotenv : .env 파일에서 환경 변수를 로드합니다.

익스프레스 웹 서버 설정
/index.js

require("dotenv").config();
const express = require("express");
const app = express();

app.use(express.json());

const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Listening on port ${port}...`));


환경 변수 구성
/.env

DB = "mongodb://localhost/node-auth-api/"
JWTPRIVATEKEY = "secretkey"
SALT = 10


MongoDB 데이터베이스 구성
/db.js

const mongoose = require("mongoose");

module.exports = async () => {
    try {
        const connectionParams = {
            useNewUrlParser: true,
            useUnifiedTopology: true,
            useCreateIndex: true,
        };
        await mongoose.connect(process.env.DB, connectionParams);
        console.log("connected to database.");
    } catch (error) {
        console.log("could not connect to database", error);
    }
};


index.js에서 db.js 가져오기 및 호출

//...
const connection = require("./db");
const express = require("express");
const app = express();

connection();
app.use(express.json());
//...


사용자 모델 만들기
/models/user.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const jwt = require("jsonwebtoken");
const Joi = require("joi");

const userSchema = new Schema({
    name: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        required: true,
    },
    password: {
        type: String,
        required: true,
    },
});

userSchema.methods.generateAuthToken = function () {
    const token = jwt.sign({ _id: this._id }, process.env.JWTPRIVATEKEY);
    return token;
};

const User = mongoose.model("user", userSchema);

const validate = (user) => {
    const schema = Joi.object({
        name: Joi.string().required(),
        email: Joi.string().email().required(),
        password: Joi.string().required(),
    });
    return schema.validate(user);
};

module.exports = { User, validate };


우리가 한 일:
  • 이름, 이메일 및 비밀번호로 사용자 테이블을 만들었습니다.
  • JWT를 사용하면 사용자 ID의 페이로드로 토큰을 생성합니다.
  • Joi와 함께 데이터를 검증합니다.

  • 경로 등록
    /routes/users.js

    const { User, validate } = require("../models/user");
    const bcrypt = require("bcrypt");
    const express = require("express");
    const router = express.Router();
    
    router.post("/", async (req, res) => {
        try {
            const { error } = validate(req.body);
            if (error) return res.status(400).send(error.details[0].message);
    
            const user = new User(req.body);
    
            const salt = await bcrypt.genSalt(Number(process.env.SALT));
            user.password = await bcrypt.hash(user.password, salt);
            await user.save();
    
            res.send(user);
        } catch (error) {
            console.log(error);
            res.send("An error occured");
        }
    });
    
    module.exports = router;
    


    로그인 경로
    /routes/auth.js

    const { User } = require("../models/user");
    const bcrypt = require("bcrypt");
    const Joi = require("joi");
    const express = require("express");
    const router = express.Router();
    
    router.post("/", async (req, res) => {
        try {
            const { error } = validate(req.body);
            if (error) return res.status(400).send(error.details[0].message);
    
            const user = await User.findOne({ email: req.body.email });
            if (!user) return res.status(400).send("Invalid email or password");
    
            const validPassword = await bcrypt.compare(
                req.body.password,
                user.password
            );
            if (!validPassword)
                return res.status(400).send("Invalid email or password");
    
            const token = user.generateAuthToken();
            res.send(token);
        } catch (error) {
            console.log(error);
            res.send("An error occured");
        }
    });
    
    const validate = (user) => {
        const schema = Joi.object({
            email: Joi.string().email().required(),
            password: Joi.string().required(),
        });
        return schema.validate(user);
    };
    
    module.exports = router;
    


    인증 미들웨어
    /미들웨어/auth.js

    const jwt = require("jsonwebtoken");
    
    module.exports = (req, res, next) => {
        try {
            const token = req.header("x-auth-token");
            if (!token) return res.status(403).send("Access denied.");
    
            const decoded = jwt.verify(token, process.env.JWTPRIVATEKEY);
            req.user = decoded;
            next();
        } catch (error) {
            res.status(400).send("Invalid token");
        }
    };
    


    사용자 경로 가져오기
    /routes/users.js

    const auth = require("../middleware/auth");
    //...
    
    router.get("/me", auth, async (req, res) => {
        try {
            const user = await User.findById(req.user._id).select("-password -__v");
            res.send(user);
        } catch (error) {
            console.log(error);
            res.send("An error occured");
        }
    });
    
    module.exports = router;
    


    Index.js에서 경로 가져오기

    //...
    const users = require("./routes/users");
    const auth = require("./routes/auth");
    //...
    
    app.use(express.json());
    
    app.use("/api/users", users);
    app.use("/api/auth", auth);
    
    //...
    


    그게 다야 서버를 실행하고 API를 테스트하십시오. 실수를 발견했거나 코드를 개선한 경우 댓글로 알려주세요. 나는 당신이 무언가를 배웠기를 바랍니다.

    고맙습니다...

    좋은 웹페이지 즐겨찾기