Node.js 상에서 로그인 세션을 관리하는 패키지인 Express-session을 사용하게 되면, 별도의 관리 로직을 구성하지 않아도 알아서 Request와 Response에 로그인 정보를 담아준다.

​

하지만 로그인에 따라 각 다른 페이지를 구성하거나, 노출 여부를 결정하는 경우라면 각 라우터의 URL 매칭마다 이를 확인해주어야 한다.

​

매번 똑같은 함수를 계속해서 호출하거나, 복붙 할 수 없으므로 Middleware 형태의 인증 확인 절차를 거친다.

​

아래와 같은 코드를 많이 보았을 텐데, 실제 이와 같이 처리하게 되면 해당 라우터를 거치는 모든 요청들이 ensureLoggedIn 함수를 거쳐 로그인 여부가 판단되고, 로그인 페이지로 리다이렉트하거나 라우터로 가던길 계속 간다.

​

​

router.get('/', auth.ensureLoggedIn(), function(req, res, next) {
return res.end();
});
 
//auth
function ensureLoggedIn(redirection) {
return function(req, res, next) {
if (req.isAuthenticated && req.isAuthenticated()) {
return next();
}
return res.redirect(redirection || '/auth/login');
};
}

당연히 Rest API도 라우터로 처리하는데, 문제는 Ajax 콜을 보내는 경우 해당 요청이 로그인 상태가 아니라면 Ajax 요청에 대한 응답이 Login 페이지로 온다는 것이다.

​

이 문제를 해결하기 위해서는, Ajax 호출하기 전에 헤더에 이 요청이 Rest API 요청임을 뜻하는 값을 추가해주고 ensureLoggedIn 함수에서 해당 헤더를 발견하면, 리다이렉트가 아닌 특정 위치로 이동하라는 의미의 헤더를 추가하여 응답해주어야 한다.

​

따라서 클라이언트단과 서버단의 코드를 아래와 같이 고쳐야한다.

​

/*call ajax request*/
function sendAjax(url, data, callback, params) {
$.ajax({
type: 'post',
url: url,
contentType: 'application/json; charset=UTF-8',
beforeSend: function(xhr) {
xhr.setRequestHeader("calltype", "API");
},
timeout: 3000,
data: JSON.stringify(data),
async: true,
success: function(data, status, xhr) {
if (xhr.getResponseHeader('redirect')) {
window.location.href = xhr.getResponseHeader('redirect');
}
callback(null, data, params, status, xhr);
},
error: function(xhr, status, message) {
callback(status, null, params);
}
});
}

위 코드는 단순 Ajax 호출을 편하게 하려고 만든 함수일 뿐이고, 주요 포인트는 beforeSend와 Success시 xhr.getResponseHeader함수이다.

​

물론 Complete함수도 있지만, Complete과 Success로 로직을 구분하여 실행하면 사용자 입장에서는 알림창과 동시에 성공에 대한 콜백도 실행되므로 Success 함수로 처리하는게 깔끔하다.

​

또한 beforeSend는 jQuery 로드 직후 글로벌하게 설정할 수 있으나, 나는 별로 그러고 싶지않아 sendAjax함수를 호출할 때마다 넣어주기로 했다. (취향차이임)

​

위의 서버단 ensureLoggedIn 함수를 아래와 같이 변경해야한다.

​

router.get('/', auth.ensureLoggedIn(), function(req, res, next) {
return res.end();
});
 
// auth
function ensureLoggedIn(redirection) {
return function(req, res, next) {
if (req.isAuthenticated && req.isAuthenticated()) {
return next();
} else {
if(req.headers.calltype && req.headers.calltype=='API') {
res.setHeader('redirect', redirection || '/auth/login'); return res.end();
}
return res.redirect(redirection || '/auth/login');
}
};
}

서버단에는 단순히 요청 헤더를 따서 API이라면, redirect 헤더를 추가하고 응답을 하는 코드가 추가된 것이다.