首页 > 解决方案 > Passport.js isAuthenticated() 在 heroku 上总是返回 false,但在本地运行服务器时正常工作

问题描述

我正在使用 passport.js 进行身份验证以及快速会话在客户端上存储 cookie。此外,我的客户是一个反应应用程序。我仍然不确定这是服务器端问题还是客户端问题。无论如何,当我在本地运行我的节点服务器,然后从我的 react 应用程序登录时,cookie 存储在本地并且我已通过身份验证,因此如果我访问需要身份验证的路由,我将获得访问权限。但是,当我在 Heroku 和相同的 react 应用程序上运行相同的服务器代码时,我从 React 应用程序登录,护照。验证工作并将成功消息发送回客户端但是由于某种原因现在如果我访问受保护的路由,我的服务器无法验证客户端。我知道 cookie 已存储,因为一旦我切换到本地服务器,我就会再次通过身份验证,这意味着 cookie 与客户端一起存在。我'

Node.js 服务器代码BACKEND


    const app = express();
    
    mongoose.connect("mongodb+srv://admin:" + process.env.DBPASS + "@cluster0.xpbd4.mongodb.net/" + process.env.DBNAME + "?retryWrites=true&w=majority", {
      useNewUrlParser: true,
      useUnifiedTopology: true
    });
    mongoose.set("useCreateIndex", true);
    
    app.use(cors({origin: "http://localhost:3000", credentials: true}));
    app.use(bodyParser.urlencoded({
      extended: true
    }));
    app.enable('trust proxy'); // add this line
    app.use(session({
      secret: process.env.SECRET,
      resave: false,
      saveUninitialized: false,
      store: new MongoStore({ mongooseConnection: mongoose.connection })
    }));
    app.use(passport.initialize());
    app.use(passport.session());
    
    passport.use(User.createStrategy());
    passport.serializeUser(function(user, done) {
      console.log("serializing user")
      done(null, user.id);
    });
    passport.deserializeUser(function(id, done) {
      console.log("deserializeUser called: " + id)
      User.findById(id, function(err, user) {
        done(err, user, function(){
          console.log("deserializeUserError: " + err)
        });
      });
    });

登录路径


    app.post("/login", function(req, res) {
      const user = new User({
        email: req.body.email,
        password: req.body.password
      });
      req.login(user, function(err) {
        console.log("req.login called")
        if (err) {
          console.log(err)
          res.send("Nuts! An unknown error occured")
        } else {
          passport.authenticate("local")(req, res, function() {
            res.send("success")
          });
        }
      });
    });

告诉用户他们是否经过身份验证的路由。当服务器在 Heroku 上时返回 false,但在本地运行时返回 true。


    app.get("/user/auth", function(req, res){
      console.log("auth called");
      if (req.isAuthenticated()) {
        res.send("true")
      } else {
        res.send("false")
      }
    })

我登录用户的前端React App


    function submit(event){
        event.preventDefault();
        axios({
          method: 'post',
          data: Querystring.stringify(user),
          withCredentials: true,
          url: props.serverURL + '/login',
          headers: {
            'Content-type': 'application/x-www-form-urlencoded'
          }
        }).then(res => {
          console.log("resdata: " + res.data)
          if (res.data === "success"){
            props.reAuth();
            props.history.push('/');
          }else{
            setResult((prevValue) => {
              return (
                res.data.toString()
              )
            });
          }
        }).catch(function(err){
          setResult((prevValue) => {
            return (
              "Invalid email or password"
            )
          });
        })
      }

最近应用程序中检查身份验证的部分


    function reAuth(){
        axios.get(serverURL + "/user/auth", {withCredentials: true}).then(res => {
          console.log(res.data)
          setAuth(res.data)
        })
      }

标签: reactjsherokuaxiospassport.jsexpress-session

解决方案


我遇到了一个问题,我的护照会话无法在 res.redirect 中幸存下来,我发现我在序列化和反序列化函数中缺少一个返回语句,即使我在本地运行它可能对你有用

passport.serializeUser(function(user, done) {
  console.log("serializing user")
  return done(null, user.id);
});
passport.deserializeUser(function(id, done) {
  console.log("deserializeUser called: " + id)
  User.findById(id, function(err, user) {
    return done(err, user, function(){
      console.log("deserializeUserError: " + err)
    });
  });
});

推荐阅读