Post

nodejs 공부 2024.06.20

과제 & 공부

로그인구현

로그인 구현시 주의

쿼리에 바로 변수를 붙이면 안됨

1
const sql = `SELECT * FROM user WHERE id = '${req.body.id}'`

이렇게 하면 로그인시 유저가 db를 악의적인 마음을 품고 삭제할 수도 있음

로그인주의1
로그인주의2

에러

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 맨 밑에에

보내고 다시 위에서 보내려고 하면 애러가 남

  1. res.send('test') 코드가 실행되면, 이 코드는 HTTP 응답을 클라이언트에게 보내고 응답 헤더와 함께 ‘test’라는 본문을 전송. 이 순간 응답이 완료됨.
  2. 그러나 이후 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 * 해서 전부 꺼내오면 성능이 떨어질 수 있음 필요한것만 가져와야함

join

저기 위에 닉네임을 가져올 수 있음 그리고 format하고 가져오기! 쿼리에서 바로 format이 가능.

깃허브 코드

06-20 깃허브 링크

This post is licensed under CC BY 4.0 by the author.