본문 바로가기

Back-end/JS

JWT, middleware

인증 프로세스

사용자요청
미들웨어(인증)
데이터처리

Model에서의 데이터 처리

몽구스에서 statics와 methods를 통해 데이터 처리 함수를 정의한다.

methods의 경우 새로 만든 객체를 통한 데이터 대입등에 이용하고 static의 경우 조회같은 단순 결과에 주로 이용합니다.

this

arrow function을 사용을 피하는게 좋은데
this 메서드를 사용할 수 없기 때문이다.

예시

UserSchema.methods.generateAuthToken = function () {
    var user = this;
    var access = 'auth';
    var token = jwt.sign({_id: user._id.toHexString(), access}, 'abc123').toString();
 
    user.tokens.push({access, token});
 
    return user.save().then(() => {
        return token;
    });
};

컨트롤러에서의 사용

// POST /users/login {email, password} 
app.post('/users/login', (req, res) => {
    var body = _.pick(req.body, ['email', 'password']);
 
    User.findByCredentials(body.email, body.password).then((user) => {
 
        //아이디 비밀번호가 맞으면 새로운 토큰을 준다. 
        return user.generateAuthToken().then((token) => {
            res.header('x-auth', token).send(user);
        });
    }).catch((e) => {
        res.status(400).send();
    });
});

pre middleware 사용

UserSchema.pre('save', function (next) {
    var user = this;
 
    if (user.isModified('password')) {
        bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(user.password, salt, (err, hash) => {
                user.password = hash;
                next();
            });
        });
    } else {
        next();
    }
});

pre를 통하여 save를 실행될 경우 패스워드가
변경되었나를 감지한 후 변경되었을 경우 hash값을 만들어 설정하여준다.

middle ware의 사용

var {User} = require('./../models/user');
 
var authenticate = (req, res, next) => {
    var token = req.header('x-auth');
 
    User.findByToken(token).then((user) => {
        if (!user) {
            return Promise.reject();
        }
 
        req.user = user;
        req.token = token;
        next();
    }).catch((e) => {
        res.status(401).send();
    });
};
 
module.exports = {authenticate};
 

인증이 필요할 경우 token 값에 x-auth값을 받은 후
해당 토큰값을 찾는다. 그 후 then과 catch를 통해
promise 패턴을 이용하여 준다. 또한 토큰값 조회를 통하여 유저정보를 request에 추가 한 후 넘겨준다.

findByToken 매서드 에서는

UserSchema.statics.findByToken = function (token) {
    var User = this;
    var decoded;
 
    try {
        decoded = jwt.verify(token, 'abc123');
    } catch (e) {
        return Promise.reject();
    }
 
    return User.findOne({
        '_id': decoded._id,
        'tokens.token': token,
        'tokens.access': 'auth'
    });
};

데이터가 맞을 경우 리턴값을 넣어주고 아닐 경우 Promise.reject를 통해 .catch(e)를 실행되도록 한다.