簡體   English   中英

Node js 護照的 req.isAuthenticated 總是返回 false

[英]Node js passport's req.isAuthenticated returns always false

我知道有很多類似的問題,我檢查了之前提出的問題,但沒有一個答案能解決我的問題。 我現在正在開發一個簡單的身份驗證 node.js 應用程序(前端是 react-native,數據庫是 MongoDB)。 我為此使用以下軟件包:

  • 護照本地貓鼬
  • 快速會話
  • 本地護照
  • 護照

所以這里是 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;

這是用戶 model:

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;

問題就在這里,經過身份驗證(工作正常),React native 進入主頁,我想在用戶登錄時獲取一些信息。為此我使用 isLoggedIn function,它使用 req.isAuthenticated() 並始終返回 false。

我嘗試過但沒有奏效的最常見答案是

  1. 確保 session-passport.init-passport.session 行以正確的順序(這已經在我的應用程序中)
  2. 發出相關客戶端 get-post 調用(在我的 react-native 應用程序中 -> axios.post(BaseURL+url,data,{ withCredentials: true }),也在服務器應用程序中 -> var corsOptions = { origin: '*', credentials: true }; app.use(cors(corsOptions)))
  3. 有人說如果你使用 https 你必須設置 {secure:true} (我不是)
  4. 有人說“身份驗證后,passport.js 要求您重新路由/重定向”,否則不會創建 session,但很多人也遇到重定向問題。 我試過了,沒有解決問題。
  5. 有人說不要使用快速會話,使用客戶端會話(我確實嘗試過,沒有用)
  6. 有些人建議更改序列化和反序列化功能(我嘗試了在互聯網上找到的其他代碼,但都沒有工作)但問題是我的反序列化 function 從未運行(我認為這個 function 在 isAuthenticated() 之后工作並檢查用戶信息在請求上,但我的請求沒有該信息。基本上,我可以登錄應用程序,但它不會在請求中保存我的 session。)
  7. 有人建議“ express-session 嘗試延遲重定向,但是有些瀏覽器在重定向之前不會等待整個響應。因此您需要在重定向之前手動保存。” 它解決了幾乎所有人的問題,但我除外。 (在我的代碼中,您可以看到 req.session.save(() => res.send("Başarılı")); )
  8. 另外,另一個人說延遲也可以解決這個問題(我試過了,但沒有)

因此,如果有人除了這些之外還有其他解決方案,請分享。 我願意接受所有建議。

我通過稍微更改服務器代碼解決了這個問題。 自從上次我與這個項目相關的工作以來,我不得不休息一下,所以有些部分我不完全記得為什么我必須改變,但在一天結束時,代碼可以工作。

我認為快速會話和護照之間有問題,因此 session 創建但在 req.session 中沒有護照 object。

在 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 提供的一些默認代碼,但它們不起作用。 所以我開始先稍微改變 session。 為此,我需要導入一個庫來創建隨機 session-id (uuid) ,我還開始從服務器端將會話保存在一個文件中。 我想我不必導入任何庫來保存數據,我可以將所有信息保存在數據庫中,但我更喜歡使用session-file-store library 我還將護照本地庫添加到此文件中(之前僅在用戶 model 上使用過)。 最后,我必須添加body-parser庫來解析響應。 我必須指出我之前使用的是express.urlencoded() function 並且它對我的路由工作正常。 我不必使用另一個庫來解析請求正文。 據我記得,當我為 session 添加一些中間件時,這個 express.urlencoded 不起作用,我就像讓我們嘗試另一個並將 body-parser 庫放在我的代碼中,它工作正常。

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

我不知道這兩條線之間的確切區別。 但我知道它們的工作方式不同,而且似乎 body-parser 庫比 express parser 工作得更好。

我更改了我的 session 的設置

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 object 創建 id 並將其保存為請求。 此代碼在我的路由器之前工作,因此每個請求都有一個 sessionId。 I think express-session checks if a request has sessionId and is it saved to the server-side before calling genId function which means that this function is called only if the request has no session-id or the session id is not stored in the server . 瀏覽器保存您的 session Id 並為每個請求使用相同的 id。 作為對象保存在服務器中的會話包含 session 的 cookie 信息。 Passport.js 將您的用戶 ID 或用戶名放入 cookie(如果您當然已登錄),因此我們可以區分該 cookie 是否與帳戶相關。

我使用的是來自本地護照的默認策略方法,但我重新編寫了它。 LocalStrategy function 是在將請求發送到“..../login”時執行身份驗證的地方。在登錄(發布)function 中,您使用 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 的反序列化用戶方面遇到了一些問題(我的問題與使用 MongoDB 自動創建的默認 objectIds 有關)function。 它沒有給出任何錯誤,而是返回 500 作為響應。 登錄后調用 SerializeUser 並將您的信息放入 cookie。 如果您的請求具有保存在服務器端的 cookie,則會調用 DeserializeUser。

在 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!\n');
    });
  })(req, res, next);
});

我像這樣更改了我的登錄名 function。 因此,當您稍微更改 session 設置時,它實際上工作正常。 我什至刪除了 session.save() 部分,因為 session 甚至是之前創建的。 我的問題是 session 數據沒有在 session 中保存為 object 所以我試圖強制保存它。

在所有這些更改之后,服務器端工作正常。 我用 postman 測試了這段代碼,它運行良好。 然而,即使我向瀏覽器發送了一個 cookie,瀏覽器也沒有保存我的 cookie。 前端或瀏覽器有問題。 但是,服務器端的這個問題得到了解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM