본문 바로가기
STUDY/NodeJS

JWT 토큰 저장 방법들 - Cookies, HTTP인증헤더, 로컬스토리지, 세션스토리지

by Y.Choi 2024. 3. 28.
728x90
반응형

 

쿠키 (Cookies)

 

서버에서 클라이언트에게 JWT 토큰을 쿠키에 저장하여 전송할 수 있다. 쿠키는 HTTP 요청 헤더에 자동으로 포함되므로, 클라이언트 및 서버 모두에서 쉽게 액세스할 수 있고 Secure 및 HttpOnly 플래그를 사용하여 보안을 강화할 수 있다. Secure 플래그는 HTTPS 연결을 통해만 쿠키가 전송되도록 보장하고, HttpOnly 플래그는 JavaScript에서 쿠키에 접근하는 것을 방지하여 XSS 공격을 예방한다.

// 회원 로그인 라우터
router.post('/login', async (req, res) => {
    try {
        // 이메일과 비밀번호를 이용하여 사용자를 인증하고 JWT 토큰 생성
        const user = await User.findOne({ email: req.body.email });
        if (!user || !await user.comparePassword(req.body.password)) {
            return res.status(401).json({ message: '이메일 또는 비밀번호가 잘못되었습니다.' });
        }
        const token = jwt.sign({ userId: user._id }, secretKey, { expiresIn: '1h' });
        
        // JWT 토큰을 쿠키에 저장
        res.cookie('token', token, { httpOnly: true, secure: true, maxAge: 3600000 }); // 1시간 유효 기간
        res.status(200).json({ success: true, message: '로그인 성공' });
    } catch (err) {
        console.error('로그인 오류:', err);
        res.status(500).json({ message: '로그인 중 오류가 발생했습니다.' });
    }
});

// 회원 로그아웃 라우터
router.post('/logout', async (req, res) => {
    try {
        // 쿠키에서 토큰 삭제
        res.clearCookie('token');
        res.status(200).json({ success: true, message: '로그아웃 되었습니다.' });
    } catch (err) {
        console.error('로그아웃 오류:', err);
        res.status(500).json({ message: '로그아웃 중 오류가 발생했습니다.' });
    }
});

 

 

쿠키 + HttpOnly

res.cookie('token', token, { httpOnly: true, secure: true, maxAge: 3600000 }); // 1시간 유효 기간

 

 

쿠키 + Secure

res.cookie('token', token, { secure: true, maxAge: 3600000 }); // 1시간 유효 기간

 

 

쿠키 + SameSite

res.cookie('token', token, { sameSite: 'strict', secure: true, maxAge: 3600000 }); // 1시간 유효 기간

 

 

HTTP 인증헤더

app.post('/login', (req, res) => {
    // 사용자 인증 후 JWT 토큰 생성
    const token = jwt.sign({ userId: user._id }, secretKey, { expiresIn: '1h' });

    // HTTP 인증 헤더에 JWT 토큰 저장
    res.setHeader('Authorization', `Bearer ${token}`);
    res.send('로그인이 성공적으로 처리되었습니다.');
});

// 로그아웃 시 HTTP 인증 헤더에서 JWT 토큰 제거 (클라이언트는 헤더를 제거해야 함)
app.post('/logout', (req, res) => {
    // 클라이언트가 HTTP 인증 헤더를 제거해야 함
    res.send('로그아웃이 성공적으로 처리되었습니다.');
});

 

HTTP 인증 헤더는 토큰을 HTTP 요청 헤더에 직접 포함시켜 토큰이 쿠키 저장소에 노출되는 것을 방지한다.

또한 쿠키는 브라우저가 자동으로 모든 요청에 포함시키므로 CSRF 공격에 취약할 수 있는 반면 HTTP 인증헤더를 사용하면 CSRF(Cross-Site Request Forgery)를 방지 할 수 있다.

 

 

로컬 스토리지 (Local Storage)

 

클라이언트 측에서 JWT 토큰을 브라우저의 로컬 스토리지에 저장할 수 있다. 이 방법은 간단하고 사용하기 쉽지만, 보안상의 이유로 추천되지 않는다. 로컬 스토리지에 저장된 토큰은 JavaScript 코드에서 쉽게 액세스할 수 있으며, XSS(크로스 사이트 스크립팅) 공격에 취약할 수 있다.

 

// 로그인 후 로컬 스토리지에 토큰 저장
localStorage.setItem('token', token);

// 로그아웃 시 로컬 스토리지에서 토큰 제거
localStorage.removeItem('token');

 


세션 스토리지 (Session Storage)

 

로컬 스토리지와 유사하지만, 세션 스토리지에 저장된 데이터는 세션이 종료되면 제거된다. 세션 스토리지를 사용하면 토큰이 브라우저를 닫거나 탭을 닫을 때 자동으로 삭제된다. 그러나 여전히 XSS 공격에 취약할 수 있다.

// 로그인 후 세션 스토리지에 토큰 저장
sessionStorage.setItem('token', token);

// 로그아웃 시 세션 스토리지에서 토큰 제거
sessionStorage.removeItem('token');

 


웹 스토리지 API (Web Storage API)

웹 스토리지 API는 localStorage 및 sessionStorage를 포함하며, 이를 통해 클라이언트 측에서 데이터를 저장하고 검색할 수 있다. 보안 측면에서는 쿠키나 HTTP 인증 헤더를 사용하는 것이 더 안전하다.

 

728x90
반응형