所以我是一个初学者在MERN堆栈。目前正在做一个项目。我在expressjs中使用passportjs进行身份验证。现在登录页面(React)的身份验证是顺利完成,但当它到达下一页,它回到未经授权,我不能访问数据。
控制器
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import LocalStrategy from 'passport-local';
import { PoliceStation } from '../Models/policestation.model.js';
class PoliceController {
constructor() {
this.router = express.Router();
this.initializePassport();
this.initializeRoutes();
}
initializePassport() {
console.log('Initializing passport')
passport.use(
new LocalStrategy(async (username, password, done) => {
try {
console.log('Incoming username:', username);
console.log('Incoming password:', password);
const user = await PoliceStation.findOne({ name: username, password });
if (!user) {
console.log('User not found');
return done(null, false, { message: 'Incorrect username or password' });
}
console.log('User found:', user);
return done(null, user);
} catch (error) {
console.error('Error in LocalStrategy:', error);
return done(error);
}
})
);
passport.serializeUser((user, done) => {
console.log('Serialize User:', user.id);
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
console.log('Deserialize User ID:', id);
try {
const user = await PoliceStation.findById(id);
console.log('Deserialized User:', user);
done(null, user);
} catch (error) {
console.error('Deserialize User Error:', error);
done(error);
}
});
}
initializeRoutes() {
this.router.use(
session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
})
);
this.router.use(passport.initialize());
this.router.use(passport.session());
// ...
const requireLogin = (req, res, next) => {
console.log('Authentication Status:', req.isAuthenticated());
console.log('User Object:', req.user);
if (req.isAuthenticated()) {
next();
} else {
res.status(401).send('Unauthorized');
}
};
// Inside your server route handling the login
this.router.post('/login', passport.authenticate('local'), (req, res) => {
if (req.isAuthenticated()) {
// Authentication successful
const user = req.user;
console.log('Authenticated User:', user);
// Log session data
console.log('Session Data:', req.session);
res.status(200).json({ message: 'Login successful', user });
} else {
// Authentication failed
console.log('Authentication failed');
res.status(401).json({ message: 'Login failed' });
}
});
// ...
this.router.get('/checklogin', (req, res) => {
if (req.isAuthenticated()) {
console.log('User is authenticated:', req.user);
res.json({ loggedIn: true, user: req.user });
} else {
console.log('User is not authenticated');
res.json({ loggedIn: false });
}
});
}
export default PoliceController;
登录.JSX
const Login = ({ setLoggedInUser }) => {
const navigate = useNavigate();
const [name, setname] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async (e) => {
e.preventDefault();
try {
const username = name;
const response = await axios.post('http://localhost:5000/police/login', { username, password });
const { user } = response.data;
console.log('Login Response:', response);
Cookies.set('userId', user._id, { expires: 7 });
Cookies.set('token', response.data.token, { expires: 7 });
setLoggedInUser(user);
// Check login status after setting cookies
const checkLoginResponse = await axios.get('http://localhost:5000/police/checklogin');
console.log('Response Data:', checkLoginResponse.data);
console.log('Full Response:', checkLoginResponse);
navigate('/home', { replace: true });
if (checkLoginResponse.data.loggedIn) {
// Redirect or perform other actions after successful login
navigate('/home', { replace: true });
} else {
console.error('Login failed. Response:', checkLoginResponse.data);
}
} catch (error) {
console.error('Login error:', error);
console.log('Complete error object:', error);
}
};
export default Login;
HOME.JSX
const Home = () => {
const [policeOfficers, setPoliceOfficers] = useState([]);
const [error, setError] = useState(null);
console.log("This is cookie on home",Cookies)
console.log("This is cookie id in home component",Cookies.get('userId'));
console.log("Cookie TOken on page no 2: ",Cookies.get)
useEffect(() => {
const fetchData = async () => {
try {
const userId = Cookies.get('userId');
const response = await axios.get(`http://localhost:5000/police/officer/${userId}`);
setPoliceOfficers(response.data.policeOfficers);
} catch (error) {
if (error.response && error.response.status === 401) {
setError('Unauthorized. Please log in.');
} else {
setError('Error fetching police officers.');
}
}
};
fetchData();
}, []); // Empty dependency array means this effect runs once when the component mounts
}
export default Home;
所以我尝试了控制台日志记录,这些是结果。
前端控制台
Login Response: {data: {…}, status: 200, statusText: 'OK', headers: AxiosHeaders, config: {…}, …}
Login.jsx:26 Response Data: {loggedIn: false}
Login.jsx:27 Full Response: {data: {…}, status: 200, statusText: 'OK', headers: AxiosHeaders, config: {…}, …}
Home.jsx:10 This is cookie on home {attributes: {…}, converter: {…}}
Home.jsx:11 This is cookie id in home component 646e2f653433e58b4b36bbc9
Home.jsx:12 Cookie TOken on page no 2: ƒ (name) {
if (typeof document === 'undefined' || arguments.length && !name) {
return;
}
// To prevent the for loop in the first place assign an empty array
// in case there are …
Home.jsx:10 This is cookie on home {attributes: {…}, converter: {…}}
Home.jsx:11 This is cookie id in home component 646e2f653433e58b4b36bbc9
Home.jsx:12 Cookie TOken on page no 2: ƒ (name) {
if (typeof document === 'undefined' || arguments.length && !name) {
return;
}
// To prevent the for loop in the first place assign an empty array
// in case there are …
xhr.js:251
GET http://localhost:5000/police/officer/646e2f653433e58b4b36bbc9 401 (Unauthorized)
dispatchXhrRequest @ xhr.js:251
xhr @ xhr.js:49
dispatchRequest @ dispatchRequest.js:51
request @ Axios.js:148
Axios.<computed> @ Axios.js:174
wrap @ bind.js:5
fetchData @ Home.jsx:19
(anonymous) @ Home.jsx:30
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(anonymous) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
Home.jsx:10 This is cookie on home {attributes: {…}, converter: {…}}
Home.jsx:11 This is cookie id in home component 646e2f653433e58b4b36bbc9
酒店端部控制台
User found: {
location: {
type: 'Point',
coordinates: [ 53.4808, 2.2426 ]
},
_id: new ObjectId("646e2f653433e58b4b36bbc9"),
name: 'MDA',
address: 'MANCHESTER',
phone: 519255339,
password: '12345678',
__v: 5,
policeOfficers: [
new ObjectId("646e3bf76c974f42bcbb055d"),
new ObjectId("646f67acdff8e98bf7fcf530"),
new ObjectId("646fc7aa88960bcfdc00352a"),
new ObjectId("646fc7b788960bcfdc003532"),
new ObjectId("6473905b525377ad83c76d27")
]
}
Serialize User: 646e2f653433e58b4b36bbc9
Authenticated User: {
location: {
type: 'Point',
coordinates: [ 53.4808, 2.2426 ]
},
_id: new ObjectId("646e2f653433e58b4b36bbc9"),
name: 'MDA',
address: 'Manchester',
phone: 519255339,
password: '12345678',
__v: 5,
policeOfficers: [
new ObjectId("646e3bf76c974f42bcbb055d"),
new ObjectId("646f67acdff8e98bf7fcf530"),
new ObjectId("646fc7aa88960bcfdc00352a"),
new ObjectId("646fc7b788960bcfdc003532"),
new ObjectId("6473905b525377ad83c76d27")
]
}
Session Data: Session {
cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true },
passport: { user: '646e2f653433e58b4b36bbc9' }
}
User is not authenticated
Authentication Status: false
User Object: undefined
Authentication Status: false
User Object: undefined
1条答案
按热度按时间gjmwrych1#
这个问题似乎与跨请求的会话持久性有关。以下是对问题的诊断:
1.成功登录后,您的用户将通过身份验证,并在服务器上生成会话数据。此会话数据包括一个唯一的会话ID,该ID应使用Cookie在客户端和服务器之间来回传递。当服务器接收到带有有效会话ID的请求时,它会识别经过身份验证的用户并授予访问权限。
1.但是,在随后对
/police/officer/${userId}
的请求中,身份验证状态为false
,这表明会话没有跨请求持久化。最常见的原因是会话ID cookie没有被传递回服务器或服务器无法识别。以下是故障排除和解决问题的一些步骤:
1.确保cookie随请求一起发送:
您的前端axios请求应该配置为随请求发送凭据(cookie)。更新您的axios请求以包含
withCredentials: true
:2.确保服务器接受并处理凭证:
在服务器端,如果您使用CORS,请确保您的CORS配置设置为接受和处理凭据:
3.使用持久会话存储:
默认的会话存储
memoryStore
是为开发而设计的,不适合生产环境,因为它在大多数情况下都会泄漏内存,并且不能扩展到单个进程。你应该为Redis使用更健壮的会话存储,比如connect-redis
,或者连接到你的数据库。4.检查cookie设置:
确保
express-session
中的会话cookie设置正确设置:5.查看服务器日志:
始终关注服务器日志。查找与会话创建、检索或身份验证相关的任何潜在错误或异常行为。
通过执行上述步骤,您应该能够识别并修复MERN应用程序中的会话持久性问题。