해결된 질문
작성
·
265
·
수정됨
0
안녕하세요 선생님
상황)req.logout안에 콜백 함수넣어서 로그아웃이 잘 되고 있었는데, isLoggedIn추가 후 상태코드 401이 뜨고 preview에는 로그인이 필요합니다가 뜨며 로그아웃 안되는 상황입니다.
network
로그인 했을 때
로그아웃 했을 때
network
로그아웃 했을 때
preview
redux
로그인 했을 때
로그아웃 했을 때
시도해본것)
로그인 후 세션정보 콘솔 출력
router.post('/login', isNotLoggedIn, (req, res, next)=> {
passport.authenticate('local',(err, user, info) => {
if(err) {
console.error(err);
return next(err);
}
if(info) {
return res.status(401).send(info.reason);
}
return req.login(user,async(loginErr)=> {
if(loginErr) {
console.error(loginErr);
return next(loginErr);
}
console.log('로그인 후 세션 정보:', req.session);
//생략
});
})(req, res, next);
}); //POST /user/login
user.js의 logout에서 에러 발생시 출력 => 출력 x
router.post('/logout', isLoggedIn, (req, res) => {
req.logout((err) => {
if (err) {
console.error(err);
return res.status(500).send('로그아웃 중 오류가 발생했습니다.');
}
res.send('ok');
req.session.destroy();
});
});
Middlewares에서 req.isAuthenticated()확인 => 결과 false
exports.isLoggedIn = (req, res, next) => {
console.log('로그인 상태 확인:', req.isAuthenticated());
if(req.isAuthenticated()) {
next();
} else {
res.status(401).send('로그인이 필요합니다.');
}
}
질문)req.isAuthenticated가 false로 나와서 로그아웃이 안되는데 원인과 해결방법이 궁금합니다. 혹시 로그인하면 이것을 true가 되게 바꾸는 방법이 있나요?
req.isAuthenticated()
작성한 코드)
UserProfile
import React, {useCallback} from 'react';
import {useDispatch, useSelector} from 'react-redux';
import {Card, Avatar, Button} from 'antd';
import styled from 'styled-components';
import {logoutRequestAction} from '../reducers/user';
const ButtonWrapper = styled(Button)`
display: block;
margin-left: auto;
margin-right: auto;
`
const UserProfile = () => {
const dispatch = useDispatch();
const { me, logOutLoading } = useSelector((state) => state.user);
const onLogout = useCallback(()=>{
dispatch(logoutRequestAction());
}, []);
return (
//생략
<ButtonWrapper onClick={onLogout} loading={logOutLoading}>로그아웃</ButtonWrapper>
);
}
export default UserProfile;
reducers/user
import {produce} from 'immer';
export const initialState = {
logOutLoading: false,//logout시도중
logOutDone: false,
logOutError: null,
}
export const LOG_OUT_REQUEST = 'LOG_OUT_REQUEST';
export const LOG_OUT_SUCCESS = 'LOG_OUT_SUCCESS';
export const LOG_OUT_FAILURE = 'LOG_OUT_FAILURE';
export const logoutRequestAction = () => {
return {
type: LOG_OUT_REQUEST
}
}
const reducer = (state = initialState, action) => produce(state, (draft) => {
switch(action.type){
case LOG_OUT_REQUEST:
draft.logOutLoading = true;
draft.logOutDone = false;
draft.logOutError = null;
break;
case LOG_OUT_SUCCESS:
draft.logOutLoading = false;
draft.logOutDone = true;
draft.me = null;
break;
case LOG_OUT_FAILURE:
draft.logOutLoading = false;
draft.logOutError = action.error;
break;
default:
break;
}
});
export default reducer;
sagas/user
import axios from 'axios';
import { all, call, delay, fork, put, takeLatest } from 'redux-saga/effects';
import {
LOG_OUT_FAILURE,
LOG_OUT_REQUEST, LOG_OUT_SUCCESS,
} from '../reducers/user';
function logOutAPI(){
return axios.post('/user/logout');
}
function* logOut() {
try{
yield call(logOutAPI);
yield put({
type: LOG_OUT_SUCCESS,
});
} catch(err) {
yield put({
type: LOG_OUT_FAILURE,
error: err.response.data
});
}
}
function* watchLogOut(){
yield takeLatest(LOG_OUT_REQUEST, logOut);
}
export default function* userSaga() {
yield all ([
fork(watchLogOut),
])
}
routes/user.js
const express = require('express');
const bcrypt = require('bcrypt');
const {User, Post} = require('../models');
const router = express.Router();
const passport = require('passport');
const {isLoggedIn, isNotLoggedIn} = require('./middlewares');
router.post('/login', isNotLoggedIn, (req, res, next)=> {
passport.authenticate('local',(err, user, info) => {
if(err) {
console.error(err);
return next(err);
}
if(info) {
return res.status(401).send(info.reason);
}
return req.login(user,async(loginErr)=> {
if(loginErr) {
console.error(loginErr);
return next(loginErr);
}
const fullUserWithoutPassword = await User.findOne({
where: {id: user.id},
attributes:{
exclude:['password']
},
include: [{
model: Post
}, {
model: User,
as:'Followings',
}, {
model: User,
as:'Followers'
}]
})
return res.status(200).json(fullUserWithoutPassword);
});
})(req, res, next);
}); //POST /user/login
//생략
const {isLoggedIn, isNotLoggedIn} = require('./middlewares');
router.post('/logout', isLoggedIn, (req, res) => {
req.logout(() => {
req.session.destroy();
res.send('ok');
});
});
routes/middlewares
exports.isLoggedIn = (req, res, next) => {
if(req.isAuthenticated()) {
next();
} else {
res.status(401).send('로그인이 필요합니다.');
}
}
exports.isNotLoggedIn = (req, res, next) => {
if(!req.isAuthenticated()){
next();
} else {
res.status(401).send('로그인 하지 않은 사용자만 접근이 가능합니다.');
}
}
passport/index
const passport = require('passport');
const local = require('./local');
const { User } = require('../models');
module.exports = () => {
passport.serializeUser((user,done) => {
done(null,user.id);//첫번째 인자 에러, 두번째 인자 성공(쿠키와 묶어줄 user아이디만 저장)
});
passport.deserializeUser(async(id, done) => {
try {
const user = await User.findOne({where:{id}})
done(null,user);
} catch(error) {
console.error(error);
done(error);
}
});
local();
};
passport/local
const passport = require('passport');
const {Strategy:LocalStrategy} = require('passport-local');
const bcrypt = require('bcrypt');
const {User} = require('../models');
const express = require('express');
const router = express.Router();
router.post('/login', passport.authenticate('local'));
module.exports = () => {
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
}, async(email, password, done) => {
try {
const user = await User.findOne({
where:{email}
});
if(!user) {
return done(null, false, {reasone: '존재하지 않는 이메일입니다!'})
}
const result = await bcrypt.compare(password, user.password);
if(result) {
return done(null, user);//성공에 사용자 정보 넘겨줌
}
return done(null, false, {reason:'비밀번호가 틀렸습니다.'});
} catch(error) {
return done(error);
}
}));
}
사용 하는 OS )mac
설치 버전)
back
{
"name": "react-nodebird-back",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "luckyhaejin",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-session": "^1.17.3",
"mysql2": "^3.6.5",
"passport": "^0.7.0",
"passport-local": "^1.0.0",
"sequelize": "^6.35.2",
"sequelize-cli": "^6.6.2"
},
"devDependencies": {
"nodemon": "^2.0.22"
}
}