본문 바로가기

Node.js

[Node.js] 로그인 기능

https://youtu.be/HcAYHUHTNi4?si=_P73OEjAh9ODPZq1

 

https://youtu.be/yWRj4GxFcr8?si=Qf7vOOcYPnV1p9Mb

 

본 포스팅은 John Ahn님의 유튜브 강의를 참고하였습니다.

 

오늘은 로그인 기능을 구현해 보도록 하겠습니다.

 

먼저 로그인 Route를 server.js에서 만들어 줍니다.

 

app.post('/login', (req,res)=>{
   //로그인 데이터를 가져온다
})

 

로그인을 하려면 3가지 단계가 필요합니다.

 

1. 로그인 하려는 이메일이 데이터베이스에 존재하는지 확인한다.

 

2. 이메일이 존재한다면 비밀 번호가 맞는 비밀번호인지 확인한다.

 

3. 비밀 번호가 맞다면 토큰을 생성한다.

 

 

 

먼저 첫 번째 단계부터 구현해 보도록 하겠습니다.

 

 User.findOne({email:req.body.email}, (err, user)=>{
           if(!user){return res.json({
            loginSuccess: false,
            message: "제공된 이메일에 해당하는 유저가 없습닏다."
        })
    }

 

findOne은 데이터가 있는지 확인하는 MongoDB에서 제공하는 함수이고,

 

req.body.email은 사용자가 입력하는 이메일 입니다.

 

이게 존재하지 않는다면 if문이 실행됩니다.

 

email이 존재한다면 2단계로 넘어가면 됩니다.

 

user.comparePassword(req.body.password, (err, isMatch) =>{
       
    })

    })

 

비밀 번호가 일치하는지 확인해야 하는데 이것은 Model의 Schema파일에서 구현합니다.

 

userSchema.methods.comparePassword = function(plainPassword, cb){
    bcrypt.compare(plainPassword, this.password, function(err, isMatch){
        if(err) return cb(err),
        cb(null, isMatch)
    })
}

 

여기서 부터 내용이 조금 어려워 지는 느낌이 들었습니다.

 

plainPassword는 기존 암호화가 되지 않은 password를 의미하고

 

cb는 콜백함수입니다.

 

암호화된 password를 복호화 할 수 는 없기 때문에 bcrypt모듈이 제공하는 compare함수를 이용해서

 

plainPassword와 암호화된 this.password를 비교하고 isMatch를 반환합니다.

 

다시 server.js 파일로 돌아가서

 

   user.comparePassword(req.body.password, (err, isMatch) =>{
        if(!isMatch)
        return res.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})

 

isMatch가 false라면 loginSuccess가 false라는 데이터와 메세지를 반환합니다.

 

그리고 isMatch가 true라면 3단계 토큰 생성으로 넘어갑니다.

 

토큰 생성을 위해서는 JsonWebToken(JWT)이라는 라이브러리를 설치해야 합니다.

 

npm i jsonwebtoken --save

 

터미널을 열고 위 코드를 입력해 설치합니다.

 

jsonwebtoken - npm (npmjs.com)

 

jsonwebtoken

JSON Web Token implementation (symmetric and asymmetric). Latest version: 9.0.2, last published: 6 months ago. Start using jsonwebtoken in your project by running `npm i jsonwebtoken`. There are 26523 other projects in the npm registry using jsonwebtoken.

www.npmjs.com

 

사용법은 JWT홈페이지를 참고해야합니다.

 

먼저 schema 파일로 가서

 

var jwt = require('jsonwebtoken');

 

jwt를 import해옵니다.

 

userSchema.methods.generationToken = function(cb){
    var user = this;
    var token = jwt.sign(user._id, 'secretToken')
    user.token = token
    user.save(function(err, user){
        if(err) return cb(err)
        cb(null, user)
    })
}

 

그 다음 작성할 코드입니다.

 

sign이라는 함수로 user._id와 'secretToken'이라는 문자로 합쳐진 토큰이 생성됩니다.

 

토큰이 생성되면 user.Token 즉, 데이터베이스에 있는

token:{
        type: String
    },

 

여기에 토큰이 저장됩니다.

 

그리고 save함수를 통해 user정보가 server.js에 있는

 

 user.generateToken((err,user)=>{
            if(err) return res.status(400).send(err);
           
        })

 

user 파라미터로 넘어오게 됩니다.

 

이제 토큰을 저장해야 하는데

 

토큰은 쿠키와 로컬 저장소에 주로 저장하는데

 

이번에는 쿠키에 저장해보도록 하겠습니다.

 

쿠키를 사용하려면 express에서 제공하는

 

cookie parser라는 라이브러리를 설치해야 합니다.

 

npm i cookie-parser 

 

터미널에 입력해서 설치해줍니다.

 

const cookieParser = require('cookie-parser');
app.use(cookieParser());

 

그리고 import하고 app.use를 통해서 사용할 수 있게 됩니다.

 

 res.cookie("x_auth",user.token)
            .status(200)
            .json({loginSuccess : true, userId : user._id})

 

 

cookie라는 함수에 (이름, 들어갈 데이터)를 입력하고

 

성공하면 작성된 json데이터를 반환합니다.

 

여기까지가 라우팅과 토큰 함수까지 구현 마무리인데

 

라우팅 부분에서 콜백함수에 대한 에러가 발생했습니다.

 

저는 몽구스가 최신 버전이기에 코드를 조금 수정해야 할 필요가 있습니다.

 

app.post("/login", async (req, res) => {
    try {
        // Check requested email in DB
        const user = await User.findOne({ email: req.body.email });

        if (!user) {
            return res.json({
                loginSuccess: false,
                message: "Not matched User Name",
            });
        }

        // Check requested password and if it is correct
        const isMatch = await user.comparePassword(req.body.password);

        if (!isMatch) {
            return res.json({ loginSuccess: false, message: "Wrong password" });
        }

        // Generate and save token
        await user.generateToken();

        // Set Token as a cookie and send a success response
        res
            .cookie("x-auth", user.token)
            .status(200)
            .json({ loginSuccess: true, userId: user._id });

    } catch (error) {
        // Handle any unexpected errors
        console.error(error);
        return res.status(500).send("Internal Server Error");
    }
});


 

 

수정한 코드입니다.

 

변한 부분은 콜백 함수를 await와 catch문으로 대체한 점 입니다.

 

이제 postman으로 로그인이 잘 되는지 확인해볼까요?

 

MongoDB 회원정보

 

현재 몽고DB에 email은 "itisme", pasword는 "123456"이 암호화 되어서 저장되어 있습니다.

 

이메일과 패스워드가 맞다면 loginSuccess : true 상태와 userID를 반환할 것이고,

 

에러가 난다면 에러 지점의 메세지를 띄워줄 것입니다.

 

 

먼저 login페이지로 맞는 데이터를 전송하여 post요청을 해보겠습니다.

 

Postman Result

성공값을 반환하는 모습입니다.

 

 

틀린 email

 

이번에는 email을 변경해서 전송해보겠습니다.

 

MongoDB result

 

loginSuccess : "false"와 UserName이 존재하지 않는다는 메세지를 출력하는 모습입니다.

 

 

 

 

오늘은 Postman을 이용해서 로그인 기능을 구현해봤는데요.

 

쿠키와 JWT라는 개념이 낯설게 느껴졌는데

 

제법 알게 된 것 같고,

 

Input으로 데이터를 받아서 로그인 기능을 구현하면

 

재밌을 것 같다는 기분이 드네요

 

긴 포스팅 읽어주셔서 감사합니다!

 

 

'Node.js' 카테고리의 다른 글

[Node.js] 로그아웃 기능  (0) 2024.02.17
[Node.js] Auth 기능 만들기  (0) 2024.02.16
[Node.js] 정보 암호화 및 관리2 - Bcrypt  (0) 2024.02.15
[Node.js, Git] 정보 암호화 및 관리  (0) 2024.02.14
[Node.js] Nodemon 모듈  (0) 2024.02.14