nodejs 공부 2024.06.20
과제 & 공부
로그인구현
로그인 구현시 주의
쿼리에 바로 변수를 붙이면 안됨
1
const sql = `SELECT * FROM user WHERE id = '${req.body.id}'`
이렇게 하면 로그인시 유저가 db를 악의적인 마음을 품고 삭제할 수도 있음
에러
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 세션 로그인
app.post('/login', (req, res) => {
console.log(req.body)
// 1. id에 해당하는 유저 정보를 db에서 꺼냄
const sql = `SELECT * FROM user WHERE id = ?`;
// 연결된 db에 쿼리를 실행
connection.query(sql, [req.body.id], (err, result) => {
if (err) {
console.error('데이터베이스 오류:', err);
return res.status(503).send('서버 오류');
}
if(!result) {
const resultHtml = `<script>
alert('없는 회원');
location.href = '/login';
</script>`;
return res.status(403).send(resultHtml)
}
console.log(result);
});
// 2. 로그인pw, 유저 정보의 hash되어 있는 pw 검증
// 3. 정보가 확인되면 (인증 성공) 세션 발급
// - 인증실패, 에러화면 or 로그인화면 다시 redirect
res.send('test')
})
이유 1
js에서 result가 없을때 /login으로 리다이렉트 하려는 함수 만들다가 저렇게 false일때 보내는걸로 하려고 했는데 js에서는 [] 을 true로 보고 있다. 그리고 send 맨 밑에에
보내고 다시 위에서 보내려고 하면 애러가 남
res.send('test')
코드가 실행되면, 이 코드는 HTTP 응답을 클라이언트에게 보내고 응답 헤더와 함께 ‘test’라는 본문을 전송. 이 순간 응답이 완료됨.- 그러나 이후
connection.query
의 콜백 함수 내부에서res.status(503).send('서버 오류')
또는res.status(403).send(resultHtml)
를 실행하려고 할 때, 이미 응답이 완료된 상태에서 다시 응답을 보내려고 하기 때문에ERR_HTTP_HEADERS_SENT
오류가 발생.
이 문제를 해결하기 위해서는 응답을 보내기 전에 모든 필요한 조건 검사를 완료해야 함. 예를 들어, 데이터베이스 쿼리가 완료된 후 그 결과에 따라 한 번만 응답을 보내도록 로직을 조정해야 함. 아래는 이를 반영하면 아래에 send를 삭제해주면 됨
이유 2
if(!result) 라고 되어있는데 js는 [] 빈배열도 true로 받아들임 그래서 false이 !result는 안먹힘
true 값으로 초기화한 Boolean 객체 만들기
1
2
3
4
5
6
var btrue = new Boolean(true);
var btrueString = new Boolean("true");
var bfalseString = new Boolean("false");
var bSuLin = new Boolean("Su Lin");
var bArrayProto = new Boolean([]);
var bObjProto = new Boolean({});
false 값으로 초기화한 Boolean 객체 만들기
1
2
3
4
5
var bNoParam = new Boolean();
var bZero = new Boolean(0);
var bNull = new Boolean(null);
var bEmptyString = new Boolean("");
var bfalse = new Boolean(false);
해결
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 세션 로그인
app.post('/login', (req, res) => {
console.log(req.body)
// 1. id에 해당하는 유저 정보를 db에서 꺼냄
const sql = `SELECT * FROM user WHERE id = ?`;
// 연결된 db에 쿼리를 실행
connection.query(sql, [req.body.id], (err, result) => {
if (err) {
console.error('데이터베이스 오류:', err);
return res.status(503).send('서버 오류');
}
if(!result || result.length === 0) {
const resultHtml = `<script>
alert('사용자 정보를 찾을 수 없습니다');
location.href = '/login';
</script>`;
return res.status(403).send(resultHtml)
}
console.log(result);
res.send('hello');
});
// 2. 로그인pw, 유저 정보의 hash되어 있는 pw 검증
// 3. 정보가 확인되면 (인증 성공) 세션 발급
// - 인증실패, 에러화면 or 로그인화면 다시 redirect
})
이렇게 length를 0으로 주면 false가능해짐
유저가 없는지랑 비번이 틀렸는지랑 두개를 따로 알려주면 보안에 취약함
비번이 틀렷거나 유저가 없다고 둘 다 말하거나 하나만 계속 알려주는게 나음
서버 껏다 키면 세션 데이터 사라짐
JOIN으로 data 가져오기
select * 해서 전부 꺼내오면 성능이 떨어질 수 있음 필요한것만 가져와야함
저기 위에 닉네임을 가져올 수 있음 그리고 format하고 가져오기! 쿼리에서 바로 format이 가능.
깃허브 코드
This post is licensed under CC BY 4.0 by the author.