Passport js isAuthenticated() 返回 false

问题描述 投票:0回答:1

所以我是 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
reactjs express authentication passport.js mern
1个回答
0
投票

该问题似乎与跨请求的会话持久性有关。这是问题的诊断:

  1. 成功登录后,您的用户将通过身份验证,并在服务器上生成会话数据。此会话数据包括一个唯一的会话 ID,应使用 cookie 在客户端和服务器之间来回传递。当服务器收到具有有效会话 ID 的请求时,它会识别经过身份验证的用户并可以授予访问权限。

  2. 但是,在对

    /police/officer/${userId}
    的后续请求中,身份验证状态为
    false
    ,这表明会话未跨请求持久保存。最常见的原因是会话 ID cookie 未传回服务器或未被服务器识别。

以下是一些排除故障和解决问题的步骤:

1.确保 cookie 与请求一起发送:

您的前端 axios 请求应配置为随请求发送凭据(cookie)。更新您的 axios 请求以包含

withCredentials: true
:

await axios.post('http://localhost:5000/police/login', { username, password }, { withCredentials: true });
// ...
await axios.get('http://localhost:5000/police/checklogin', { withCredentials: true });
// ...
await axios.get(`http://localhost:5000/police/officer/${userId}`, { withCredentials: true });

2.确保服务器接受并处理凭据:

在服务器端,如果您使用 CORS,请确保您的 CORS 配置设置为接受和处理凭据:

import cors from 'cors';

app.use(cors({
  origin: 'http://localhost:3000', // your React app's domain
  credentials: true
}));

3.使用持久会话存储:

默认会话存储

memoryStore
是为开发而设计的,不适合生产,因为它在大多数情况下会泄漏内存,并且无法扩展到单个进程。您应该使用更强大的会话存储,例如 Redis 的
connect-redis
或连接到您的数据库。

4.检查 cookie 设置:

确保

express-session
中的会话cookie设置正确:

this.router.use(
  session({
    secret: 'your-secret-key',
    resave: false,
    saveUninitialized: true,
    cookie: {
      httpOnly: true,
      secure: false, // set to true if using HTTPS
      maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days in milliseconds
    }
  })
);

5.检查服务器日志:

始终关注服务器日志。查找与会话创建、检索或身份验证相关的任何潜在错误或异常行为。

通过执行上述步骤,您应该能够识别并修复 MERN 应用程序中的会话持久性问题。

© www.soinside.com 2019 - 2024. All rights reserved.