diff --git a/backend/package-lock.json b/backend/package-lock.json index 4f76ba6c45ff7a85518efd0ba411229f242dff69..a5544933432c9c1a3b91bc8b7ee9b9a667dd41df 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -10,9 +10,11 @@ "license": "ISC", "dependencies": { "axios": "^1.6.1", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "moment": "^2.29.4", "mongoose": "^8.0.1", "nodemon": "^3.0.1" }, @@ -341,6 +343,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -835,6 +857,14 @@ "node": "*" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/mongodb": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.2.0.tgz", diff --git a/backend/package.json b/backend/package.json index 510aea71b0752ac0bb9910d759e27aac74d749b1..7f53a52bb2382775e9a25bd85794befd841acb82 100644 --- a/backend/package.json +++ b/backend/package.json @@ -13,9 +13,11 @@ "license": "ISC", "dependencies": { "axios": "^1.6.1", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "moment": "^2.29.4", "mongoose": "^8.0.1", "nodemon": "^3.0.1" }, diff --git a/backend/src/index.js b/backend/src/index.js index c4fac91a266a79c52b169ff191c7a28b2c8db5c2..0f262aeaa6b6655a5573aac914d8d192a8ef44cc 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -2,6 +2,8 @@ import express from "express" import cors from 'cors' import path from 'path' import process from 'process' +import moment from 'moment'; +import cookieParser from 'cookie-parser'; import db from './db.js' @@ -12,19 +14,21 @@ db.connectDB(); app.use(express.static(path.join(process.cwd(), '../frontend/build'))); +app.use(cookieParser()); app.use(express.json()); app.use(express.urlencoded({ extended: false })); -app.use(cors()); +app.use( + cors({ + origin: 'http://localhost:3000', + credentials: true, + }) +); //cors 설정을 한다.. app.listen(PORT, () => { console.log(`Listening on port ${PORT}`); }); // 서버 실행 -/* -app.get('/', function (req, res) { - res.sendFile(path.join(process.cwd(), '../frontend/build/index.html')); -}); -*/ + function b64_to_utf8( str ) { return decodeURIComponent(escape(window.atob( str ))); } @@ -34,10 +38,16 @@ function encode_utf8(s) { } app.post('/login', (req, res) => { - const text = req.body; - console.log(req.body); + /* + TODO: 토큰의 무결성 체크 + 토큰이 이상이 없다면, 로그인/회원가입 로직을 수행 후 jwt 쿠키를 보낸다. + */ + const expires = moment().add('2','m').toDate() + res.cookie('jwt', JSON.stringify(req.body), {expires}); + + //통과 못하면 에러를 뱉는다 res.send(req.body.name); - //res.redirect(200, "/main"); + }); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 649748646aa5121f4253bfb16efb822012666e5c..ed59d0a57cfdd9339a8192be8d186fbe00716253 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,7 +16,10 @@ "base-64": "^1.0.0", "express": "^4.18.2", "jwt-decode": "^4.0.0", + "moment": "^2.29.4", "react": "^18.2.0", + "react-cookie": "^6.1.1", + "react-cookies": "^0.1.1", "react-dom": "^18.2.0", "react-kakao-maps-sdk": "^1.1.24", "react-router-dom": "^6.18.0", @@ -4264,6 +4267,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.4.tgz", + "integrity": "sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==" + }, "node_modules/@types/eslint": { "version": "8.44.7", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz", @@ -4323,6 +4331,15 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -9618,6 +9635,19 @@ "he": "bin/he" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -13418,6 +13448,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -13587,7 +13625,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -15705,6 +15742,36 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "dev": true }, + "node_modules/react-cookie": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-6.1.1.tgz", + "integrity": "sha512-fuFRpf8LH6SfmVMowDUIRywJF5jAUDUWrm0EI5VdXfTl5bPcJ7B0zWbuYpT0Tvikx7Gs18MlvAT+P+744dUz2g==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "hoist-non-react-statics": "^3.3.2", + "universal-cookie": "^6.0.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, + "node_modules/react-cookies": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/react-cookies/-/react-cookies-0.1.1.tgz", + "integrity": "sha512-PP75kJ4vtoHuuTdq0TAD3RmlAv7vuDQh9fkC4oDlhntgs9vX1DmREomO0Y1mcQKR9nMZ6/zxoflaMJ3MAmF5KQ==", + "dependencies": { + "cookie": "^0.3.1", + "object-assign": "^4.1.1" + } + }, + "node_modules/react-cookies/node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -18137,6 +18204,15 @@ "node": ">=8" } }, + "node_modules/universal-cookie": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-6.1.1.tgz", + "integrity": "sha512-33S9x3CpdUnnjwTNs2Fgc41WGve2tdLtvaK2kPSbZRc5pGpz2vQFbRWMxlATsxNNe/Cy8SzmnmbuBM85jpZPtA==", + "dependencies": { + "@types/cookie": "^0.5.1", + "cookie": "^0.5.0" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index c45d5805d8999686dc231a7c442dbff5854a062a..bfb51ec6b34f95305e05754bfc0e8460f982c1b3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,10 @@ "base-64": "^1.0.0", "express": "^4.18.2", "jwt-decode": "^4.0.0", + "moment": "^2.29.4", "react": "^18.2.0", + "react-cookie": "^6.1.1", + "react-cookies": "^0.1.1", "react-dom": "^18.2.0", "react-kakao-maps-sdk": "^1.1.24", "react-router-dom": "^6.18.0", diff --git a/frontend/src/GoogleLoginButton.js b/frontend/src/GoogleLoginButton.js index cf7dc2db37ac25fc769ad1a07ee80dd2f2e359a7..c0ae0354553b4db0b9e2cdbc60a2e40f21b34eab 100644 --- a/frontend/src/GoogleLoginButton.js +++ b/frontend/src/GoogleLoginButton.js @@ -1,16 +1,24 @@ import { GoogleLogin } from "@react-oauth/google"; import { GoogleOAuthProvider } from "@react-oauth/google"; import { useNavigate, Navigate } from "react-router-dom"; +import { useCookies } from 'react-cookie' + +// 안써도 자동으로 한국 시간을 불러온다. 명확하게 하기 위해 import +import moment from 'moment'; +import 'moment/locale/ko'; import base64 from 'base-64'; import axios from 'axios'; +axios.defaults.withCredentials = true; /* */ + const GoogleLoginButton = () => { + const [cookies, setCookie, removeCookie] = useCookies(); const clientId = '716858812522-rb0pfisq317unkh4so5hvbu16p19kqp8.apps.googleusercontent.com' const navigate = useNavigate(); const goMain = () => { @@ -30,14 +38,19 @@ const GoogleLoginButton = () => { RS256 : 암호화 알고리즘, JWT 서명할 때 사용한다고 함 */ - - console.log(res); - + + // 쿠키 테스트 1분 뒤 만료 + const expires = moment().add('1','m').toDate() + setCookie('cookieTest','hello',{expires}) + let datas = res.credential.split('.') const obj = JSON.parse(b64DecodeUnicode(datas[1])); - console.log(obj); - let response = commuTest(obj); - console.log(response); + + // 토큰을 보내 로그인 로직 처리 + // 로그인이 정상적으로 되었다면 쿠키를 등록 + + let response = requestLogin(obj); + console.log(cookies.jwt) if (response) { goMain(); } @@ -60,23 +73,19 @@ function b64DecodeUnicode(str) { }).join('')); } -async function commuTest(payloadObj) { - +async function requestLogin(payloadObj) { const response = await axios({ url: 'http://localhost:8080/login', // 통신할 웹문서 method: 'post', // 통신할 방식 data: payloadObj }); - console.log(response) - if (response.status === 200) { return response.data; } else { return null; } - } export default GoogleLoginButton \ No newline at end of file