티스토리 뷰
cookie 튜토리얼
CORS 설정
CORS 설정은 이러한 Same-Origin Policy를 우회하기 위해 서버에서 브라우저에게 특정 출처에서 자원에 대한 액세스를 허용하도록 허용하는 메커니즘입니다. 이를 통해, 다른 출처의 자원을 안전하게 사용
const corsOptions = {
// client는 http://localhost:3000 을 이용
origin: "http://localhost:3000",
// cookie는 인증 정보를 포함하는 경우가 많으므로 credentials도 설정
//credentials 속성은 자격 증명 정보를 포함하는 요청을 허용할지 여부를 결정
credentials: true,
// 허용할 메소드를 배열에 담아서 작성
methods: ['GET', 'POST', 'OPTION']
};
flow 이해
1.client : 버튼 클릭하면 서버로 로그인 요청을 보내기
2.server : 로그인 요청 처리(회원가입 되어있는지 확인)
회원이면 응답에 쿠키와 회원정보 담아서 전달
3. client : 응답을 받아 react상태 업데이트
4. client : 화면 리렌더링
로그인 유지 옵션 체크 => 서버에서 받아온 쿠기를 사용해서 회원정보 받아옴 ,쿠키 유지 시간만큼 자동 로그인 유지
5. client : 로그아웃 버튼 눌러 서버로 로그아웃 요청을 보내기
6.server : 로그아웃 요청 처리(쿠키 삭제 후 클라이언트로 응답 보냄)
7. client : 응답이 들어오면 react 상태 초기화
8. client : 화면 리렌더링 => 로그인 페이지
client 측
Login,js
일부
export default function Login({ setIsLogin, setUserInfo }) {
const [loginInfo, setLoginInfo] = useState({
userId: '',
password: '',
});
const [checkedKeepLogin, setCheckedKeepLogin] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const handleInputValue = (key) => (e) => {
setLoginInfo({ ...loginInfo, [key]: e.target.value });
};
const loginRequestHandler = () => {
if (!loginInfo.userId || !loginInfo.password) {
setErrorMessage('아이디와 비밀번호를 입력하세요')
// 입력되지 않은 값으로 요청을 보내볼 필요도 없이 바로 리턴
return;
} else{
setErrorMessage('');
}
return axios
.post("http://localhost:4000/login", {loginInfo, checkedKeepLogin})
/*login을 담당하는 endpoint*/
.then((res) => {
/* 로그인에 성공했다면 응답으로 받은 데이터가 Mypage에 렌더링되도록 State를 변경*/
console.log(res.data)
setUserInfo(res.data)
setIsLogin(true)
//여기에서 에러 초기화
setErrorMessage("")
})
.catch((err) =>
console.log(err.response.data)
if (err.response.status === 401) {
setErrorMessage("로그인에 실패했습니다.")
}
});
};
:
:
Mypage
일부
export default function Mypage({ userInfo, setIsLogin, setUserInfo }) {
const logoutHandler = () => {
return axios
.post("http://localhost:4000/logout")
.then((res) => {
setUserInfo(null);
setIsLogin(false);
})
.catch((err) => {
alert(err);
});
};
:
:
//로그아웃 버튼 누를 시 userInfo는 null , isLogin는 false가 된다.
App.js
function App() {
const [isLogin, setIsLogin] = useState(false);
const [userInfo, setUserInfo] = useState(null);
const authHandler = () => {
//TODO: 초기 화면 렌더링시, 서버에 유저 정보를 요청하여 Login 또는 Mypage가 렌더링되도록 구현
return axios
.get('http://localhost:4000/userinfo')
.then((res) => {
setIsLogin(true);
setUserInfo(res.data);
})
.catch((err) => {
if (err.response.status === 401) {
console.log(err.response.data);
}
});
};
useEffect(() => {
authHandler();
}, []);
return (
<BrowserRouter>
<div className='main'>
<Routes>
<Route
path='/'
element={
isLogin ? (
<Mypage
isLogin={isLogin}
setIsLogin={setIsLogin}
setUserInfo={setUserInfo}
userInfo={userInfo}
/>
) : (
<Login
setIsLogin={setIsLogin} setUserInfo={setUserInfo}
/>
)
}
/>
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
server 측
login.js
onst { USER_DATA } = require('../../db/data');
module.exports = (req, res) => {
const { userId, password } = req.body.loginInfo;
const { checkedKeepLogin } = req.body;
const userInfo = {
...USER_DATA.filter((user) => user.userId === userId && user.password === password)[0],
};
console.log(req.body)
//로그인 성공 시에는 클라이언트에 쿠키를 전송
//쿠키의 cookieId에는 userInfo.id가 담겨야 된다.
console.log(userInfo)
var cookiesOption = {
domain: 'localhost',
path: '/',
httpOnly: true,
sameSite: 'none',
secure: true,
}
if (userInfo.id === undefined) {
res.status(401).send('Not Authorized')
}
else if (checkedKeepLogin === true) {
cookiesOption.maxAge = 1000 * 60 * 30
//30분동안 쿠키를 유지
cookiesOption.expires = new Date(Date.now() + (1000 * 60 * 30) )
// 지금 시간 + 30분 후에 쿠키를 삭제한다는 의미
res.cookie('cookieId', userInfo.id, cookiesOption)
res.redirect("/userinfo")
} else {
res.cookie('cookieId', userInfo.id, cookiesOption)
res.redirect("/userinfo")
}
};
userinfo.js
const { USER_DATA } = require('../../db/data');
module.exports = (req, res) => {
const cookieId = req.cookies.cookieId
const userInfo = {
...USER_DATA.filter((user) => user.id === cookieId)[0],
};
if (!cookieId || !userInfo.id){
res.status(401).send('Not Authorized');
} else {
// 비밀번호는 민감한 정보라서 삭제 후에 보내야 합니다.
delete userInfo.password
res.send(userInfo)
}
};
logout.js
module.exports = (req, res) => {
//cookie-parser의 clearCookie('쿠키의 키', cookieOption) 메서드로 해당 키를 가진 쿠키를 삭제
const cookiesOption = {
domain: 'localhost',
path: '/',
httpOnly: true,
sameSite: 'none',
secure: true,
}
res.status(205).clearCookie('cookieId', cookiesOption).send("logout")
};
Session 튜토리얼
서버측
login.js
const { USER_DATA } = require('../../db/data');
module.exports = (req, res) => {
const { userId, password } = req.body.loginInfo;
const { checkedKeepLogin } = req.body;
const userInfo = {
...USER_DATA.filter((user) => user.userId === userId && user.password === password)[0],
};
if (!userInfo.id) {
res.status(401).send("Not Authorized")
} else if (checkedKeepLogin) {
req.session.sessionId = userInfo.id
console.log(req.session)
req.session.cookie.maxAge = 1000 * 60 * 30
res.redirect('/userinfo')
} else {
req.session.sessionId = userInfo.id
res.redirect('/userinfo')
}
};
userinfo.js
const { USER_DATA } = require('../../db/data');
module.exports = (req, res) => {
const sessionId = req.session.sessionId
const userInfo = {
...USER_DATA.filter((user) => user.id === sessionId)[0],
};
if (!sessionId || !userInfo.id){
res.status(401).send('Not Authorized');
} else {
delete userInfo.password
res.send(userInfo)
}
};
logout.js
module.exports = (req, res) => {
req.session.destroy();
res.status(205).send('Logged Out Successfully');
};
'codestates > section3' 카테고리의 다른 글
과제 - Tokens 과 OAuth2.0 (0) | 2023.03.08 |
---|---|
과제 - 웹 표준 & 접근성 개선 (0) | 2023.03.02 |
알고리즘rotatedArraySearch (0) | 2023.03.02 |
알고리즘power (0) | 2023.02.28 |
SEO에 영향을 미치는 요소 (0) | 2023.02.28 |