节点js Passport的req.isAuthenticated返回始终为false

Node js passport#39;s req.isAuthenticated returns always false(节点js Passport的req.isAuthenticated返回始终为false)
本文介绍了节点js Passport的req.isAuthenticated返回始终为false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多类似的问题,我检查了之前提出的问题,没有一个答案能解决我的问题。我目前正在开发一个简单的身份验证node.js应用程序(前端是原生的,数据库是MongoDB)。为此,我使用以下软件包:

  • Passport-Local-Mongoose
  • Express-Session
  • 护照-本地
  • 护照

这里是app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require('cors');
var passport = require('passport');
var user = require('./models/user');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var cookieParser = require('cookie-parser')
var app = express();
app.use(cookieParser('keyboard cat'));


var corsOptions = {
  origin: '*',
  credentials: true };
app.use(cors(corsOptions))



app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));


app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

//auth settings
app.use(require("express-session")({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: false,
}));

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

passport.use(user.createStrategy());
passport.serializeUser(user.serializeUser());
passport.deserializeUser(user.deserializeUser());



app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

以下是用户模型:

var mongoose=require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');

var userShema = new mongoose.Schema({
    username : String,
    password : String
})

userShema.plugin(passportLocalMongoose);


var user= mongoose.model("User",userShema);

module.exports = user;    
     

这是我的路由文件

var express = require('express');
var router = express.Router();
var user= require("../models/user");
const passport = require('passport');
var isLoggedIn =require('../session');
/* GET home page. */
router.get('/', function(req, res, next) {
 
  res.render('index', { title: 'Express' });
});

router.post('/login', function(req, res, next) {
  passport.authenticate('local' ,function(err, user, info) {
    if (err) { return next(err); }
    if (!user) { return res.send("-1"); }
    
    req.logIn(user, function(err) {

      if (err) { return next(err); }
      req.session.save(() => res.send("Başarılı"));
    });
  })(req, res, next);
});


router.post('/signUp', async function(req, res, next) {
  try{

    console.log('registering user');
    user.register(new user({username: req.body.username}), req.body.password, function(err) {
      if (err) {
        console.log('error while user register!', err);
        return next(err);
      }
      console.log('user registered!');
      res.redirect('/');
    });
 
  }
  catch(e){
    console.log(e);
    res.status(503).send("-1")
  }
 
 
  
});

router.get('/logOut', function(req,res,next){
  req.logOut();
  res.send("1");
})

router.get('/home',isLoggedIn,function(req,res,next){
  res.send("Success");
})

module.exports = router;

最后是session.js

const passport = require('passport');
var isLoggedIn =(req,res,next) =>{
    if(req.isAuthenticated()){
        return next();
    }
    res.status(403).send("Something went wrong")
}


module.exports = isLoggedIn;

这里的问题是,在身份验证(该方法工作正常)之后,原生Reaction转到主页,我希望在用户登录时获取一些信息。为此,我使用isLoggedIn函数,该函数使用req.isAuthenticated()并返回始终为false。

我尝试过但不起作用的最常见答案是

  1. 确保session-passport.init-passport.session行顺序正确(已在我的应用程序中)
  2. 发出相关客户端GET-POST调用(在我的REACT-NATIVE app->;axios.post(BaseURL+url,data,{with Credentials:true})中),也在服务器app->;var corsOptions={ 来源:‘*’, 凭证:true}; app.use(CORS(CorsOptions))
  3. 有人说如果您使用https,则必须设置{Secure:true}(我没有设置)
  4. 有人说&q;认证后,passport.js要求您重新路由/重定向&q;,否则不会创建会话,但是很多人在重定向方面也有问题。我确实试过了,但没有解决问题。
  5. 有人说不要使用Express-Session,使用Client-Session(我试过了,没有用)
  6. 有人建议更改序列化和反序列化函数(我尝试了在Internet上找到其他代码,但都不起作用),但问题是我的反序列化函数从未运行过(我认为此函数在isAuthenticated()之后工作,并检查请求的用户信息,但我的请求没有该信息。基本上,我可以登录到该应用程序,但它不会在请求中保存我的会话。)
  7. 有人建议";express-session尝试延迟重定向,但有些浏览器在定向之前并不等待整个响应。所以在重定向之前你需要手动保存。它解决了几乎所有人的问题,除了我。(在我的代码中,您可以看到req.session.save(()=>;res.send(";Başarılı";);)
  8. 另外,另一个人说延迟也可以解决这个问题(我试过了,但是没有)

因此,如果任何人在这些解决方案之外还有其他解决方案,请与我们分享。我愿意接受所有建议。

推荐答案

我稍微更改了一下服务器代码就解决了这个问题。自从上次从事与此项目相关的工作以来,我不得不休息一下,所以有些部分我不太记得为什么要更改,但是,在一天结束时,代码可以正常工作。

我认为Express-Session和Passport之间有问题,因此在req.session中创建了会话,但没有Passport对象。

在App.js中,我必须添加一些新库:

const { v4: uuidv4 } = require('uuid');
const FileStore = require('session-file-store')(session);
const LocalStrategy = require('passport-local').Strategy;
const bodyParser = require("body-parser");

我以前使用过Express-Session和Passport提供的一些默认代码,它们不起作用。所以我开始先稍微改变一下课程。为此,我需要导入库以创建随机会话id(Uuid),还启动了以从服务器端将会话保存在文件中。我想我不必导入任何库来保存数据,我可以保存数据库中的所有信息,但我更喜欢使用会话文件存储库。我还将Passport-local库添加到此文件中(它以前只在用户模型上使用过)。最后,我必须添加主体解析器库来解析响应。我必须指出我以前使用的是expression s.urlencode()函数,它对我的路由工作得很好。我不必使用另一个库来解析请求正文。就我所记得的,当我为会话添加一些中间件时,这个表达式.urlencode不起作用,我想让我们尝试另一个,并将正文解析器库放入我的代码中,它工作得很好。

app.use(bodyParser.urlencoded({ extended: false })); 
app.use(express.urlencoded({ extended: false }))

我不知道这两行之间的确切区别。但我知道它们的工作方式不同,主体解析器库似乎比表达式解析器工作得更好。

我更改了会话的设置

app.use(session({
  genid: (req) => {
    console.log('Inside the session middleware')
    console.log(req.sessionID)
    return uuidv4(); // use UUIDs for session IDs
  },
  store: new FileStore(),
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true
}))
因此,基本上我使用Session对象创建id,并将其保存为request。此代码在我的路由器之前运行,因此每个请求都有一个sessionId。我认为express-session会在调用genID函数之前检查请求是否有sessionId,以及它是否保存到服务器端,这意味着只有当请求没有session-id或者会话id没有存储在服务器中时才会调用该函数。 浏览器保存您的会话ID,并对每个请求使用相同的ID。作为对象保存在服务器中的会话保存会话的Cookie信息。Passport.js 将您的用户ID或用户名放入Cookie(当然,如果您已登录),以便我们可以区分该Cookie是否与帐户相关。

我使用的是来自Passport-local的默认策略方法,但我重写了它。LocalStrategy函数是当请求发送到‘./login’时执行身份验证的位置。在LOGIN(POST)函数中,您可以使用passport.Authenticate(‘local’,function(err,user,info){}->;这里local表示使用您在app.js

中决定的本地策略
passport.use(new LocalStrategy(
  function(username, password, done) {
    console.log("passport localStrategy",username,password)
    user.findOne({ username: username }, function (err, user) {
       user.authenticate(password).then(res => {
        if (err) { return done(err); }
        if (!user) { return done(null, false); }
        if (!res.user) { return done(null, false); }
        console.log('Local strategy works fine')
        return done(null, user);
       })
    
    });
  }
));

//takes user and save it to  session file store
//saves the user id in the request object as request.session.passport
//and adds request object as request.user.
passport.serializeUser(function(user, done) {
  console.log('Inside serializeUser callback. User id is save to the session file store here')
  done(null, user); 
});

passport.deserializeUser(function(user, done) {
  console.log('Inside De-serializeUser callback.')   
    done(null,user)
});
如果您正在使用MongoDB,我建议您不要序列化惟一的user.id(至少在您确定程序的其他部分可以正常工作之前不要这样做)。我在使用findById函数的desializeUser时遇到了一些问题(我的问题与使用MongoDB自动创建的默认objectID有关)。它没有给出任何错误,但作为响应返回到500。 SerializeUser在登录后被调用,并将您的信息放入cookie中。如果您的请求具有保存在服务器端的Cookie,则调用Anti ializeUser。

在Index.js(我的路由器文件)

 router.post('/login', function(req, res, next) {
  console.log("inside of the login",req.sessionID)

  //passport.authenticate with local parameter will call function that configured in passport.use(new strategyCalss)
  passport.authenticate('local' ,function(err, user, info) {
    console.log('Inside passport.authenticate() callback');
    console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
    console.log(`req.user: ${JSON.stringify(req.user)}`)
    if (err) { return next(err); }
    if (!user) { return res.send("-1"); }
    //req.login calls passport.serialize user
    req.login(user, function(err) {
      console.log('Inside req.login() callback')
      console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
      console.log(`req.user: ${JSON.stringify(req.user)}`)
      if (err) { return next(err); }
      return res.send('You were authenticated & logged in!
');
    });
  })(req, res, next);
});

我按如下方式更改了我的登录函数。因此,当您稍微更改会话设置时,它实际上工作得很好。我甚至删除了session.save()部分,因为会话甚至是以前创建的。我的问题是会话数据没有保存为会话中的对象,所以我尝试强制保存它。

完成所有这些更改后,服务器端工作正常。我和邮递员一起测试了这段代码,它工作得很好。但是,即使我向浏览器发送了cookie,浏览器也没有保存我的cookie。与前端或浏览器相关的问题。但是,服务器端的此问题已解决。

这篇关于节点js Passport的req.isAuthenticated返回始终为false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)