Hello, Android!

쿠키와 세션 본문

Node

쿠키와 세션

lwndnjs93 2021. 2. 5. 19:23

쿠키는 서버가 클라이언트에게 보내 클라이언트가 보관하며, 이후 서버에 요청을 할때 쿠키를 같이 보낸다

"키"="값" 의 쌍으로 이루어져 있으며, 헤더에 포함되어 서버와 클라이언트가 주고받는다

쿠키를 사용하면 정보를 통해 클라이언트는 서버에게 자신이 누구인지를 알려준다

브라우저는 쿠키를 가지고 있으면 자동으로 함께 서버에 보내주기때문에 

서버에서 클라이언트에게 쿠키를 보내고 어떤 유저인지 파악하는 부분만 만들면 된다

 

쿠키는 헤더에 포함되어 있기 때문에 node.js에서도 쿠키를 동봉할때는

writeHead 함수에서 "Set-Cookie" 를 사용하여 보내게 된다

1
2
3
4
5
6
7
8
9
10
11
const http = require("http")
 
http.createServer((req, res) => {
    console.log(req.url, req.headers.cookie)
    res.writeHead(200, {"Set-Cookie""name=ryan"})
    res.end("Hello, cookie")    
})
.listen(8080, () => {
    console.log("8080번 포트에서 대기중입니다")
})
 
cs

위와같이 헤더에 Set-Cookie에 "name=ryan" 이라고 넣고 클라이언트에게 넘겨주면

쿠키의 키는 name 이고 값은 ryan이 된다

직접 들어가 브라우저의 개발자 도구를 열어 쿠키를 확인하면

서버가 보낸 쿠키를 클라이언트가 정상적으로 받은것을 확인할 수 있다

쿠키에는 다양한 옵션을 넣을수가 있으며, 각각의 옵션들은 ; 으로 구분한다

- 쿠키명 = 쿠키값 : 쿠키의 키와 값을 설정한다

- Expries = 날짜 : 지정한 날짜가 지나면 쿠키가 제거된다 기본값은 클라이언트가 종료되면 제거된다

- Max-age = 초 : 해당 초가 지나면 쿠키가 삭제된다 Expries보다 우선 순위가 높다

- Domain = 도메인명 : 특정 도메인에만 쿠키를 전송될수 있도록 지정할수 있다 기본값은 현재 도매인이다

- Path = URL : 특정 URL에만 쿠키를 전송하도록 한다 기본값은 / 이며 모든 URL에서 쿠키를 전송할 수 있다

- Secure : HTTPS에서만 쿠키가 전송된다

- HttpOnly : 자바스크립트에서 쿠키에 접근할 수 없다 쿠키 조작 방지를 위해 설정하는 것이 좋다

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const http = require("http")
const fs = require("fs").promises
const url = require("url")
const qs = require("querystring")
 
const parseCookies = (cookie = ""=> 
    cookie
        .split(";")
        .map(v => v.split('='))
        .reduce((acc, [k,v]) => {
            acc[k.trim()] = decodeURIComponent(v)
            return acc
        }, {})
 
http.createServer(async (req, res) => {
    const cookies = parseCookies(req.headers.cookie)
 
    if(req.url.startsWith("/login")){
        const {query} = url.parse(req.url)
        const {name= qs.parse(query)
        const expires = new Date()
        expires.setMinutes(expires.getMinutes() + 5)
        res.writeHead(302, {
            Locatin: "/",
            "Set-Cookie": `name=${encodeURIComponent(name)}; Expries=${expires.toGMTString()}; HttpOnly; Path=/`
        })
        res.end()
    }else if(cookies.name){
        res.writeHead(200, {"Content-Type""text/plain; charset=utf-8"})
        res.end(`${cookies.name}님 안녕하세요`)
    }else{
        try{
            const data = await fs.readFile("./cookie2.html")
            res.writeHead(200, {"Content-Type""text/html; charset-utf-8"})
            res.end(data)
        }catch(err){
            res.writeHead(500, {"Content-Type""text/plain; charset=utf-8"})
            res.end(err.message)
        }
    }
})
.listen(8087, () => {
    console.log("8087번 포트에서 대기 중입니다")
})
cs

웹 페이지에 텍스트 박스와 버튼이 있고, 버튼을 누르면 입력한 내용을 쿠키에 저장하여 서버에 보낸 뒤

해당 페이지에 다시 접속할때 쿠키에 있는 정보를 사용하여 인사 메세지가 나온다

 

가장 먼저 parseCookies 함수가 있는데, 기본적으로 쿠키는 "name=ryan"과 같이 문자열로 오기때문에

문자열을 객체로 바꿔주는 함수이다

createServer내부의 if문을 보면 크게 세가지 경우로 구분하고 있다

1. url이 /login으로 끝나는 경우 2. /login이 아니고 쿠키가 존재하는 경우 3. /login이 아니고 쿠키도 없는 경우

 

페이지에 최초 접속하면 3번의 경우가 될것이다

이때는 텍스트박스와 버튼이 있는 html파일을 클라이언트에게 전송하게된다

cookie2.html을 받은 클라이언트는 유저에게 입력받은 값을 /login으로 전송한다

만약 ryan 이라고 입력하였다면 /login?name=ryan 이라고 보내게 된다

url을 파싱한 query는 name=ryan 이 되고 쿼리를 파싱한 결과물인 name 은 ryan이 된다

헤더에 쿠키와, 현재시간 + 5분을 쿠키 유효시간으로 넣은 뒤 종료하게 된다

만약 2번의 경우 /login이 아니지만 쿠키가 유효한 경우에는 쿠키에 있는 값을 찾아 인사말을 보낸다

 

이번에는 유저 정보를 서버가 관리하도록 수정하였다

가장 크게 달라진 부분은 session 객체에 현재 시간을 키로 사용하여 쿠키의 값과 유효시간을 관리하고 있다

클라이언트에 넘겨주는 쿠키에도 ryan 이라는 값을 넘겨주는것이 아닌 유니크한 현재 시간값, 쿠키 유효시간을 넘겨주고 있다

그리고 /login이 아니고 쿠키가 존재하는 경우에도 조건이 변경되어

쿠키가 존재하고, 서버가 가지고있는 세션 객체에서 해당 쿠키의 유효시간을 체크한 뒤

세션 객체에서 해당 쿠키의 값을 찾아 인사 메세지를 보낸다

 

이 방법이 세션이다, 서버에 클라이언트 정보를 저장하고 세션 아이디만으로 소통한다

세션 아이디는 쿠키 이외의 다른 방법으로 주고받아도 되지만, 가장 간단하여 많이 사용한다

이와같이 세션을 위해 사용하는 쿠키를 세션 쿠키 라고 한다

 

위의 두 예제의 경우 쿠키, 세션아이디가 공개되어 쿠키를 악용한 공격에 아주 취약하다

그렇기때문에 절대 실제 서비스에서는 위와 같이 사용해서는 안된다

'Node' 카테고리의 다른 글

npm pakage.json  (0) 2021.02.08
클러스터  (0) 2021.02.06
RESTful서버  (0) 2021.02.04
http서버  (0) 2021.02.03
이벤트 처리  (0) 2021.02.02