TIL 57์ผ์ฐจ Cookie / Session ๐ช
๋ค์ด๊ฐ๋ฉฐ
๋ณด์ ์์ ์ฒซ ๋ . Section3์์ ๊ฐ์ฅ ์ค์ํ ์์ ์ ํ๋ ๊ณ ๋ฅด๋ฉด ๋๊ตฌ๋ ์ด ์์ ์ ๊ณ ๋ฅธ๋ค๊ณ ํ ์ ๋๋ก ์ค์ํ ์์ ์ด๋ค. ์ด๋ฒ์ฃผ๋ ํน๋ณ ์ฃผ๊ฐ์ผ๋ก ๋ถ๋ฅผ ์ ๋๋ก ์ค์ํ ๋ด์ฉ๋ค์ด ๋ชฐ๋ ค์๋ค. Cookie์ Session. ์์ง๋์ด ์ํํ๋ฉด์ ์ด๋ ดํํ ๊ฐ๋ ์ ์์์ง๋ง ์ง์ ๋ค๋ฃจ๋๊ฑด ์ฝ์ง ์๊ตฌ๋. ๋ช ๋ น์ด๋ ์ด์ํ๊ณ MVC ํจํด๋ ์์ง ์ด์ง ์ด์ํ๋ค. ๊ทธ ์ํ์์ ๋ณด์์ ๋๋ ค๋ฃ์ผ๋.. ์์ฐ! ํ๋ฃจ ๋ฐฐ์ฐ๊ณ ๋์ด๊ฐ Sequelize๋ ํ์ด๋์จ๋ค. ์ด๊ฑด ๋ณต์ต์ ์ํ๋ฉด ๋์ ํ ๋ฐ๋ผ๊ฐ ์ ์๋ค.
์คํ๋ฆฐํธ๋ ์ฝ์ง ์์๋ค. ๋ณ๋ช
์ ํ์๋ฉด, ํ
์คํธ ์ผ์ด์ค๊ฐ ๋์จํ๊ฒ ์ง์ฌ์์ด์ ์ค์ ๋ก Header์ Cookie๊ฐ ๋ค์ด์์ง ์์๋ ๋ค์ด์๋ค๊ณ ํต๊ณผ๊ฐ ๋๋ค. ์ด๊ฑธ ๋ชฐ๋ผ์ ํ~์ฐธ์ ํด๋งธ๋ค.
axios
์ฌ์ฉ์ ๋ํด์๋ ๊ท๋ ํด์คฌ๋ค๋ฉด ์ด๋ ๊ฒ ํด๋งค์ง ์์๋ค. ์ค๋์ ํ์ด์ ๊ฐ์ด ๋๋ฌด ํด๋งค์ ์ ์ ์ ์ผ๋ก ์ง์น๋ ํ๋ฃจ๋ค. ๊ทธ๋๋ ํด๋งค๋ฉด์ ๋ฐฐ์ด๋ค๊ณ .. ์ฐจ๋ผ๋ฆฌ ํ ๋ฒ์ ์ฑ๊ณตํ์ง ๋ชปํ๊ฒ ์คํ๋ ค ๋์ด ๋์ง ์์๊น? ๋ด๊ฐ ๋ง์ด ๋ถ์กฑํ๊ณ ๋ณด์ถฉํด์ผ ๋๋ค๊ณ ๋๋ผ๋ ๊ณ๊ธฐ๊ฐ ๋์ง ์์๊น? ์กฐ๊ธ์ ๋์๊ฒ ์๋ก๋ฅผ ํด๋ณธ๋ค.
์ด๋ฒ ํฌ์คํ
์ ์ค์ต ๊ณผ์ ์์ ๋์ณค๋ ๋ถ๋ถ์ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํ๋ค. ๋ถ์กฑํ ๋ถ๋ถ์ ๋ช๋ฒ์ฉ ๋ฐ๋ณตํด์ผ๊ฒ ๋ค.
์ฐ๋ฉด์ ๊ถ๊ธํด์ก๋๋ฐ ์ฌ๋ฌ๊ฐ์ ํด๋ผ์ด์ธํธ๊ฐ ์์ ๋, ์ ์ฒด ์ธ์ ์ ์กฐํํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ๋ ๊น?
์ธ์ ๊ณผ ์ฟ ํค
์ธ์ ๋ฑ๋ก๊ณผ ์ฟ ํค๋ฅผ ์ ์กํ๋ ๋ถ๋ถ์ ํ๋ฌดํ ์ ๋๋ก ์ฝ๋ค. sessionId๋ userId๋ก ์ง์ ํ๊ณ ๊ฐ ํฌํจํด์ ๋ณด๋ด์ฃผ๋ฉด ๋.
req.session.userId = req.body.userId;
res.status(200).json({ data: userInfo, message: 'ok' }).end();
๋ ํผ๋ฐ์ค ์ฝ๋๋ save()
๋ฉ์๋์ ์ฝ๋ฐฑํจ์๋ก ๋ค์ด๊ฐ๋ค. ๊ณต์ ๋ฌธ์์์๋ HTTP ์๋ต์ด ๋๋ ๋ ์๋์ผ๋ก ํธ์ถ๋๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๋ถ๋ฅผ ํ์๊ฐ ์๋ค.
This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.
session - expressjs
req.session.save(function () {
req.session.userId = userInfo.userId;
res.json({ data: userInfo, message: 'ok' });
});
์ธ์ ํ๊ธฐ
req.session ๋ด์ ํค๊ฐ์ ์ง์ฐ๋ ๊ฒ๋ณด๋ค (delete ๋ฉ์๋) req.session.destroy()
๋ฉ์๋๋ก ๋ช
์์ ์ผ๋ก ์ง์ธ ์ ์๋ค. ๊ธฐ๋ณธ ๊ฐ์ keep()
์ด๋ฉฐ ์ธ์
์ ์ ์งํ๋ค.
req.session.destroy();
res.json({ data: null, message: 'ok' });
๋ค๋ฅธ ๋๋ฉ์ธ๊ฐ ์ฟ ํค ์ ์กํ๊ธฐ
Frontend์ Backend ๋๋ฉ์ธ ์ฃผ์๊ฐ ๋ค๋ฅธ ๊ฒฝ์ฐ Cookie ์ ๋ฌ์ด ๋์ง ์๋๋ค. ํนํ Network ํญ์์ Response Header์ Set-Cookie๋ ์๋๋ฐ Application ํญ์์ Cookie๊ฐ ๋ณด์ด์ง ์๋๋ค. ํค๋์ ์ต์ ์กฐ์ ์ผ๋ก ์ด๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
client / withCredentials: true
ํค๋์ withCredentials: true
์ต์
์ผ๋ก ๋ณด์ ํต์ ์ค ๋ค๋ฅธ ๋๋ฉ์ธ(Cross) ์ฌ์ด์ ์ฟ ํค ๊ธฐ๋ฅ์ ํ์ฑํํ๋ค. ํ์ฌ ์ค์ต ํ๊ฒฝ์ ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ๋๋ฉ์ธ์ด ๋ค๋ฅธ ์ํฉ์ด๋ค.
XMLHttpRequest.withCredentials ์์ฑ์ ์ฟ ํค, ๊ถํ ๋ถ์ฌ ํค๋ ๋๋ TLS ํด๋ผ์ด์ธํธ ์ธ์ฆ์์ ๊ฐ์ ์๊ฒฉ ์ฆ๋ช ์ ์ฌ์ฉํ์ฌ ์ฌ์ดํธ ๊ฐ ์ก์ธ์ค ์ ์ด ์์ฒญ์ ๋ง๋ค์ด์ผ ํ๋์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ถ์ธ ๊ฐ์ ๋๋ค.
withCredentials ์ค์ ์ ๋์ผ ์ฌ์ดํธ ์์ฒญ์ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
withCredentials๊ฐ true๋ก ์ค์ ๋์ด ์์ง ์์ผ๋ฉด ์์ ์ ๋๋ฉ์ธ์ ๋ํ ์ฟ ํค ๊ฐ์ ์ค์ ํ ์ ์์ต๋๋ค. withCredentials๋ฅผ true๋ก ์ค์ ํ์ฌ ์ป์ ํ์ฌ ์ฟ ํค๋ ์ฌ์ ํ ๋์ผ ์ถ์ฒ ์ ์ฑ ์ ๋ฐ๋ฅด๋ฏ๋ก document.cookie ๋๋ ์๋ต ํค๋๋ฅผ ํตํด ์์ฒญํ๋ ์คํฌ๋ฆฝํธ์์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
XMLHttpRequest.withCredentials - mozilla
axios
.post(
'https://localhost:4000/users/login',
{
userId: this.state.username,
password: this.state.password,
},
{ 'Content-Type': 'application/json', withCredentials: true } // <------
)
server / credentials: true
์ด ์ต์ ์ ๋๋ฉด ์ฒซ๋ฒ์งธ ๋ก๊ทธ์ธ ์์ฒญ์์ ์๋์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ์์ฃผ ๋ณด๋ ์๋ฌ๋ค. CORS ์ ์ฑ ์ ์๋ฐ๋๋ค๋ ๋ด์ฉ์ด๋ฉฐ 'XMLHttpRequest์ ์ํด ์์๋ ์์ฒญ์ ์๊ฒฉ ์ฆ๋ช ๋ชจ๋๋ withCredentials ์์ฑ์ ์ํด ์ ์ด๋๋ค'๊ณ ํ๋ค.
Access to XMLHttpRequest at 'https://localhost:4000/users/login' from origin 'https://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
์๋๋ ๊ณต์ ๋ฌธ์์์ ์ธ๊ธํ๋ Access-Control-Allow-Credentials ์ต์ ์ ๋ํ ์ค๋ช ์ด๋ค. ์์ฝํ๋ฉด ๋ค๋ฅธ ๋๋ฉ์ธ๊ฐ ํค๋๋ฅผ ํฌํจํ ์ ์๊ฒ ํ๋ค.
์๋ตํค๋ Access-Control-Allow-Credentials ๋ ์์ฒญ์ ์๊ฒฉ์ฆ๋ช ๋ชจ๋(Request.credentials)๊ฐ "include" ์ผ๋, ๋ธ๋ผ์ฐ์ ๋ค์ด ์๋ต์ ํ๋กํธ์๋ ์๋ฐ์คํธ๋ฆฝํธ ์ฝ๋์ ๋ ธ์ถํ ์ง์ ๋ํด ์๋ ค์ค๋๋ค.
์์ฒญ์ ์๊ฒฉ์ฆ๋ช ๋ชจ๋๊ฐ (Request.credentials)๊ฐ "include" ์ผ ๋, Access-Control-Allow-Credentials ๊ฐ์ด true ์ผ ๊ฒฝ์ฐ์๋ง ๋ธ๋ผ์ฐ์ ๋ค์ ํ๋กํธ์๋ ์๋ฐ์คํธ๋ฆฝํธ์ ์๋ต์ ๋ ธ์ถ ํ ๊ฒ์ ๋๋ค.
Access-Control-Allow-Credentials - mozilla
credentials: Configures the Access-Control-Allow-Credentials CORS header. Set to true to pass the header, otherwise it is omitted.
cors - express
server / origin: 'https://localhost:3000' or true
origin์ *
๋ก ์ ์ผ๋ฉด ์๋๋ค. ์ ํํ๊ฒ ์ ์ด์ผ ์ฟ ํค๊ฐ ๋ค์ด๊ฐ๋ค. express์์ true๋ ๋ฐ์์ค๋ค.
๋ก๊ทธ์ธ ์์ฒญ์ด ์ฒด์ธ์ผ๋ก ์ฐ๊ฒฐ๋์ด์ 2๋ฒ ์ด๋ฃจ์ด์ง๋๋ฐ ๊ทธ ๊ณผ์ ์์ ์์ ํค๋๊ฐ ๋ง๋ค์ด์ ธ CORS ์ ์ฑ
์ ์๋ฐํ๋ค. ๊ฐ๋ฐ์ ๋๊ตฌ์์ ๋ณด๋ฉด ์ฒซ Login Post ์์ฒญ์ ๋์ด๊ฐ์ง๋ง ์ด์ด์ง๋ userinfo Get ์์ฒญ์ CORS ์์ ๋งํ๋ค.
๊ทธ ์ด์ ๋ origin ์ต์
์ด *
์ผ ๋๋ 'Access-Control-Allow-Origin' ์ต์
์ด ์ง์๋์ง ์๋๋ค.
Reason: Credential is not supported if the CORS header โAccess-Control-Allow-Originโ is *
app.use(
cors({
origin: 'https://localhost:3000', // <-----
methods: ['GET', 'POST', 'OPTIONS'],
credentials: true, // <------
})
);
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(TIL 57์ผ์ฐจ Cookie / Session ๐ช), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@shleecloud/TIL-57์ผ์ฐจ-Cookie-Session์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค