Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在带有React.js前端的Node.js上使用Passport.js进行身份验证_Node.js_Reactjs_Authentication_Cookies_Passport.js - Fatal编程技术网

在带有React.js前端的Node.js上使用Passport.js进行身份验证

在带有React.js前端的Node.js上使用Passport.js进行身份验证,node.js,reactjs,authentication,cookies,passport.js,Node.js,Reactjs,Authentication,Cookies,Passport.js,说到认证,我完全是个新手。我正在尝试将科尔特·斯蒂尔(Colt Steele)使用的方法作为我项目的一部分 Colt使用Node.js+Express.js+MongoDB,在ejs中进行服务器端渲染。对于用户身份验证,他使用Passport.js 我使用Node.js+Express.js+MongoDB,并使用React.js进行客户端渲染。我也使用React路由器。我还尝试使用Passport对用户进行身份验证 我的问题是,虽然我可以成功登录,但仍然无法访问登录墙后面的任何内容。当我向服务

说到认证,我完全是个新手。我正在尝试将科尔特·斯蒂尔(Colt Steele)使用的方法作为我项目的一部分

Colt使用Node.js+Express.js+MongoDB,在ejs中进行服务器端渲染。对于用户身份验证,他使用Passport.js

我使用Node.js+Express.js+MongoDB,并使用React.js进行客户端渲染。我也使用React路由器。我还尝试使用Passport对用户进行身份验证

我的问题是,虽然我可以成功登录,但仍然无法访问登录墙后面的任何内容。当我向服务器请求某个路由以检查用户是否经过身份验证时,答案总是false

这是我的身份验证码

const express = require("express"),
  server = express(),
  path = require("path"),
  mongoose = require("mongoose"),
  User = require("./models/User"),
  bodyParser = require("body-parser"),
  passport = require("passport"),
  localStrategy = require("passport-local"),
  passportLocalMongoose = require("passport-local-mongoose"),
  expressSession = require("express-session");

mongoose.connect("mongodb://localhost/diary");

server.use(
  bodyParser.urlencoded({
    extended: true
  })
);

//Auth
server.use(
  expressSession({
    secret: "This is pretty damn weird.",
    resave: false,
    saveUninitialized: false
  })
);

server.use(passport.initialize());
server.use(passport.session());

passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());    

// Auth login
server.post("/login", function(request, response) {
  passport.authenticate("local", function(err, user, info) {
    if (err) {
      return console.log(err);
    }
    if (!user) {
      return response.send(false);
    }
    request.logIn(user, function(err) {
      if (err) {
        return console.log(err);
      }
      checkLogIn(request, response);
      return response.send(true);
    });
  })(request, response);
});

//Auth checkLogIn
function checkLogIn(request, response) {
  if (request.isAuthenticated()) {
    return console.log("authenticated");
  } else {
    return console.log("not authenticated");
  }
}
因为我使用的是客户端渲染,所以无法使用response.redirect将用户重定向到任何地方。这就是为什么我使用response.send(true)(或false):我使用它们作为标志来告诉React应用程序该做什么

上面的代码与Colt的几乎相同:他将expressSession的配置保持在最低限度,并且似乎没有定义自己的本地策略或(反)序列化函数。在我发现的几个教程中,每个人似乎都这么做了,但柯尔特没有,他的应用程序运行得很好。他也不使用任何MongoStore,其他很多人似乎都这么做

正如您所看到的,我有一个checkLogIn函数,名为right after request.logIn,它只记录console.log用户是否登录。登录后,屏幕上会显示true,即登录确实成功

此时我应该登录,但如果我试图从浏览器访问受保护的分区,我会被告知我没有登录。例如,我成功地以假用户Elmo的身份登录,然后尝试访问/Elmo/diary。这将带我到一个React组件,该组件在特定路由上查询服务器,如下所示:

//Find all entries of a given user.
router.get("/entries/:userURL", isLoggedIn, (request, response) => {
  console.log("get entries");
  User.findOne(
    { customURL: request.params.userURL },
    { entryIDs: 1 },
    (err, data) => {
      //Get the actual entries.
      Entry.find({ _id: { $in: data.entryIDs } }, (err, entries) => {
        if (err) {
          console.log(err);
        } else {
          response.send(entries);
        }
      });
    }
  );
});
如您所见,我使用的是isLoggedIn中间件,如下所示:

//Auth isLoggedIn
function isLoggedIn(request, response, next) {
  console.log(request);
  if (request.isAuthenticated()) {
    console.log("logged in");
    return next();
  }
  console.log("not logged in");
  return (function() {
    response.send(false);
  })();
}
因此,如果我以Elmo身份登录,上面的路由应该返回数据。但是,无论我是否登录,中间件都会返回false

我检查了运行应用程序的localhost的cookie,其中只有一个具有令牌值(s%3Ak0SZJ97eJkPjqjE6jC-azn7y3ztK2UMw.fYOfM9324JUIeUDGvh26swEWwMf3j3HDUmh9WubNF%2B8),因此我猜Passport正在成功创建会话并将其存储在cookie中

老实说,我也不确定这个系统是如何为Colt工作的,因为他的前端似乎没有返回任何令牌/数据供后端检查,而我(承认有限)的理解是,这是应该的


知道我做错了什么吗?

当你说“登录墙”时,我假设你想进入受保护的路由/组件。我相信您需要一个带有react路由器的受保护路由,如下所示:

 //Placed near your other react router routes, pass the logged in state to this route
  <PrivateRoute path="/dashboard" component={Dashboard} loggedIn={loggedIn} />
 //If auth'd, redirect to the component you want, if not then redirect to login
const PrivateRoute = ({ component: Component, ...rest, loggedIn }) => (
  <Route
    {...rest}
    render={props => (
      loggedIn ? (
        <Component {...props} />
      ) : (
        <Redirect to={{
          pathname: '/login',
          state: { from: props.location },
        }}
        />
      )
    )}
  />
);

对于客户端路由,您使用的是react-router还是express?@Dream\u Cap react-router。登录时,loggedIn的值如何传递到所有路由?我更新了答案,以包含有关该问题的更多信息。此答案是否有帮助?我仍在努力找出答案。我现在正在学习一个Udemy课程,说react根本不需要参与,因为浏览器会自动将身份验证cookie附加到每个http请求。实际上,我并不真正需要受保护的路由,只需要身份验证来决定是否可以向用户显示某些数据。对不起,我的措辞有点混乱。无论如何,谢谢你的帮助!
const AllRoutes = ({ loggedIn }) => (
  <BrowserRouter history={history}>
    <div>
      <PrivateRoute path="/dashboard" component={Dashboard} loggedIn={loggedIn} />
       //other routes
    </div>
  </BrowserRouter>
);
   //import connect for connecting the component into redux's store(state)
import { connect } from 'react-redux';
//map redux's store to props so the component can access it (this is how loggedIn can get passed in)
const mapStateToProps = state => ({
  loggedIn: state.signup.loggedIn,
});
 //wraps the component in Redux's store(state)
export default connect(mapStateToProps, null)(AllRoutes);