diff --git a/backend/src/index.js b/backend/src/index.js index d9bb2da84abe016f46c853017fc2e4514064b8fc..222a9a94f0e164a595efa7e361ee6833a82c237e 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -87,6 +87,25 @@ app.post('/login', async (req, res) => { }); +app.get("/logout", (req, res) => { + console.log("로그아웃"); + if (req.session.sessionid) { + + console.log("로그아웃중입니다!"); + req.session.destroy((err) => { + if (err) { + console.log("세션 삭제시에 에러가 발생했습니다."); + return; + } + console.log("세션이 삭제됐습니다."); + }); + res.clearCookie('name'); + res.send(req.body.name); + } else { + console.log("로그인이 안돼있으시네요?"); + res.send(req.body.name); + } +}); diff --git a/frontend/src/App.js b/frontend/src/App.js index 6315fab6001191c58ea66a8031a50b06734369fb..1182d9d190bad87a8a9caa8ceb06111e012bcf7e 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -2,20 +2,28 @@ import "./App.css"; import {Routes, Route } from 'react-router-dom'; import Header from "./Header.js"; import Main from "./Main.js"; +import Login from "./Login.js"; import Search from "./Search.js"; import GoogleLoginButton from "./GoogleLoginButton.js"; +import React, { useEffect, useState, useContext} from 'react'; +import { UserContext } from './Usercontext.js'; function App() { + + const [ myName, setMyName] = useState(null); + return( <div className="App"> - <Header/> - <Routes> - <Route path="/" element={<Main/>}></Route> - <Route path="/search" element={<Search/>}></Route> - {/* <Route path="/postwrite" element={<PostWrite/>}></Route> */} - </Routes> - <GoogleLoginButton/> - {/* <Footer/> */} + <UserContext.Provider value={setMyName}> + <Header user={myName}></Header> + <Routes> + <Route path="/" element={<Main/>}></Route> + <Route path="/login" element={<Login/>}></Route> + <Route path="/search" element={<Search/>}></Route> + {/* <Route path="/postwrite" element={<PostWrite/>}></Route> */} + </Routes> + </UserContext.Provider> + {/* <Footer/> */} </div> ); } diff --git a/frontend/src/GoogleLoginButton.js b/frontend/src/GoogleLoginButton.js index c0ae0354553b4db0b9e2cdbc60a2e40f21b34eab..572894ab9709f36a5023454fe457bcaa3d4a14c1 100644 --- a/frontend/src/GoogleLoginButton.js +++ b/frontend/src/GoogleLoginButton.js @@ -2,6 +2,8 @@ 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 React, { useEffect, useState, useContext} from 'react'; +import { UserContext } from './Usercontext.js'; // 안써도 자동으로 한국 시간을 불러온다. 명확하게 하기 위해 import import moment from 'moment'; @@ -11,37 +13,24 @@ import base64 from 'base-64'; import axios from 'axios'; axios.defaults.withCredentials = true; -/* - -*/ - const GoogleLoginButton = () => { + + const setUserName = useContext(UserContext); + const [cookies, setCookie, removeCookie] = useCookies(); const clientId = '716858812522-rb0pfisq317unkh4so5hvbu16p19kqp8.apps.googleusercontent.com' const navigate = useNavigate(); + const goMain = () => { - navigate("/main"); + navigate("/"); } return ( <> <GoogleOAuthProvider clientId={clientId}> <GoogleLogin onSuccess={(res) => { - /* 발급받은 토큰은 . 을 기준으로 3 개로 나뉜다. - aaaa.bbbb.cccc - - [base64]aaaa: 헤더 - [base64]bbbb: 페이로드 (실질적인 데이터) - [RS256]cccc: 서명 - - RS256 : 암호화 알고리즘, JWT 서명할 때 사용한다고 함 - */ - - // 쿠키 테스트 1분 뒤 만료 - const expires = moment().add('1','m').toDate() - setCookie('cookieTest','hello',{expires}) let datas = res.credential.split('.') const obj = JSON.parse(b64DecodeUnicode(datas[1])); @@ -49,11 +38,13 @@ const GoogleLoginButton = () => { // 토큰을 보내 로그인 로직 처리 // 로그인이 정상적으로 되었다면 쿠키를 등록 - let response = requestLogin(obj); - console.log(cookies.jwt) - if (response) { - goMain(); - } + let response = requestLogin(obj).then( + (val) => { + setUserName(val) + goMain(); + } + ); + }} onFailure={(err) => { console.log("Login Failed"); @@ -79,7 +70,6 @@ async function requestLogin(payloadObj) { method: 'post', // 통신할 방식 data: payloadObj }); - console.log(response) if (response.status === 200) { return response.data; } diff --git a/frontend/src/Header.js b/frontend/src/Header.js index f3d61773084d78b614049907fc9cc691d53b8120..e95d56439335032cfff0c1102f2c0299a2a6493c 100644 --- a/frontend/src/Header.js +++ b/frontend/src/Header.js @@ -1,23 +1,118 @@ import {Link} from "react-router-dom"; import logo from './logo.png'; import './Header.css'; +import cookie from 'react-cookies'; +import React, { useEffect, useState, useContext} from 'react'; +import { useNavigate, Navigate } from "react-router-dom"; +import { UserContext } from './Usercontext.js'; +import axios from 'axios'; +axios.defaults.withCredentials = true; -function Header(){ + +function Welcome(props){ + + return ( + <p> + {props.name?`${props.name}님, 환영합니다`:'로그인하세요.'}<br/> + </p> + ) +} + +function ButtonLink({link, onclick, children}){ + + return ( + <botton onClick = {()=>{ + onclick(link)}}> + {children} + </botton> + ) +} + +function Header({user}){ + //console.log(cookie.load('name')) + const [currentSession, setCurrentSession] = useState(false) + + const setUserName = useContext(UserContext); + const navigate = useNavigate(); + function checkSession_And_Navigate(link){ + if (cookie.load('name')) { + navigate(link); + setCurrentSession(true) + } + else { + setUserName(null) + if (currentSession){ + alert('세션이 만료되었습니다. 로그인 후 이용해 주세요.') + } + else { + alert('로그인 후 이용해 주세요.') + } + + navigate("/login"); + setCurrentSession(false) + } + } + + function dont_CheckSession_And_Navigate(link){ + if (cookie.load('name')) { + setCurrentSession(true) + } + else { + setUserName(null) + if (currentSession){ + alert('세션이 만료되었습니다. 자동으로 로그아웃됩니다.') + } + setCurrentSession(false) + } + navigate(link); + } + + function logOut(){ + let response = requestLogout(); + if (response){ + setUserName(null) + alert('로그아웃되었습니다. 메인 화면으로 돌아갑니다..') + setCurrentSession(false) + navigate('/'); + } + } + return( <div className="header"> - <Link to='/'><img className="logo_image" alt="logo" src={logo}/></Link> - <ul className="menu_list"> - <li><Link to="/">Home</Link></li> - <li><Link to="/search">검색</Link></li> - <li><Link to="/postwrite">포스트 작성</Link></li> - <li><Link to="/login">로그인</Link></li> {/*로그인 여부 로직 구현 필요*/} - {/* { Object.keys(user).length != 0 ? - <li><Link to={`/profile/${getUserId()}`}>profile</Link>/<span onClick={logout}>logout</span></li> : - <li><Link to="/login">login</Link></li> - } */} - </ul> + <ButtonLink link='/' onclick={dont_CheckSession_And_Navigate}> + <img className="logo_image" alt="logo" src={logo}/> + </ButtonLink> + + <ul> + + <Welcome name={user}></Welcome> + + <ul className="menu_list"> + <li><ButtonLink link='/' onclick={dont_CheckSession_And_Navigate}>Home</ButtonLink></li> + <li><ButtonLink link='/search' onclick={checkSession_And_Navigate}>검색</ButtonLink></li> + <li><ButtonLink link='/postwrite' onclick={checkSession_And_Navigate}>포스트 작성</ButtonLink></li> + <li><ButtonLink link='/login' onclick={user?logOut:dont_CheckSession_And_Navigate}>{user?'로그아웃':'로그인'}</ButtonLink></li> {/*로그인 여부 로직 구현 필요*/} + {/* { Object.keys(user).length != 0 ? + <li><Link to={`/profile/${getUserId()}`}>profile</Link>/<span onClick={logout}>logout</span></li> : + <li><Link to="/login">login</Link></li> + } */} + </ul> + </ul> </div> ); } +async function requestLogout() { + const response = await axios({ + url: 'http://localhost:8080/logout', // 통신할 웹문서 + method: 'get', // 통신할 방식 + }); + if (response.status === 200) { + return response.data; + } + else { + return null; + } +} + export default Header; diff --git a/frontend/src/Login.js b/frontend/src/Login.js new file mode 100644 index 0000000000000000000000000000000000000000..8acde8ebf37ebb4cfcf0d8f2717b42f3bfd267ef --- /dev/null +++ b/frontend/src/Login.js @@ -0,0 +1,22 @@ +import { useNavigate } from 'react-router-dom'; +import GoogleLoginButton from "./GoogleLoginButton.js"; + +function Button({history, children}){ + const navigate = useNavigate(); + return( + <button onClick={() => {navigate('/search');}}> + {children} + </button> + ); +} + +function Login() { + return( + <div className="App"> + <h1>로그인 '해줘'</h1> + <GoogleLoginButton></GoogleLoginButton> + </div>) + ; +} + +export default Login; \ No newline at end of file diff --git a/frontend/src/Main.js b/frontend/src/Main.js index 37d91294ed771898ba06cc3e1c9a10f0b4017778..86bc01a319f531b2c073b9e0f7ccd66a51cbb9ca 100644 --- a/frontend/src/Main.js +++ b/frontend/src/Main.js @@ -1,4 +1,6 @@ import { useNavigate } from 'react-router-dom'; +import cookie from 'react-cookies'; +import React, { useState, useEffect, useContext } from 'react'; function Button({history, children}){ const navigate = useNavigate(); @@ -10,6 +12,10 @@ function Button({history, children}){ } function Main() { + + useEffect(() => { + // 컴포넌트가 불러와지면 실행이 되는군. + }); return( <div className="App"> <h1>메인 페이지 입니다.</h1> diff --git a/frontend/src/Usercontext.js b/frontend/src/Usercontext.js new file mode 100644 index 0000000000000000000000000000000000000000..6278fb7652de86e6d770f86871656bd6fa5699fc --- /dev/null +++ b/frontend/src/Usercontext.js @@ -0,0 +1,3 @@ +import { createContext } from 'react'; + +export const UserContext = createContext(null); \ No newline at end of file diff --git a/frontend/src/index.js b/frontend/src/index.js index 532f33b6b06e3fb01b749b217e7da9f09c8fb5f1..3a2e456c1996ed173a7673527e6e790c6dbfa465 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -8,7 +8,7 @@ const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <BrowserRouter> - <App/> + <App/> </BrowserRouter> </React.StrictMode> );