Node + Express + Passport:req.user未定义

时间:2013-05-08 07:20:54

标签: node.js express passport.js

我的问题类似于one,但没有深入了解他的解决方案。

我正在使用Passport使用Instagram进行身份验证。成功验证后,用户将被定向到“/”。此时,请求具有用户对象(也就是它正在工作)。但是,一旦我重定向,req.user是未定义的。 :'(

奇怪的是,每个请求都会调用passport.deserializeUser。它成功获取了用户对象,但在中间件路上的某个地方,req.user未被设置(或未被设置)。

// on successful auth, goto "/" 
app.get('/', function(req, res) {
    // if the request has the user object, go to the user page
    if (req.user) {
        res.redirect("/user/" + req.user._id);
    }

    res.render("index");
}

app.get('/user/:uid', function(req, res) {
    console.log(req.user) // undefined
}

26 个答案:

答案 0 :(得分:46)

我的问题是在客户端使用fetch时没有指定发送cookie。它包括凭证后工作:'包括'请求中的字段。

fetch('/api/foo', {credentials: 'include'})

答案 1 :(得分:36)

您是否为应用设置了会话状态?你需要这样的东西......

app.use(session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());

答案 2 :(得分:15)

我是Node的新手,但对我来说这是一个中间件问题。添加了bodyParser并重新排列以修复。

代码破碎:

app.use(express.cookieParser('secret'));
app.use(express.cookieSession());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public'))); 

工作代码:

app.use(express.static(path.join(__dirname, 'public')));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);

希望这有帮助

答案 3 :(得分:8)

以前我有这些代码(不起作用):

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    secret: 'abcdefg',
    resave: true,
    saveUninitialized: false,
    cookie: { secure: true } // this line
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

然后我从会话初始化程序中删除cookie选项:

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    secret: 'abcdefg',
    resave: true,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

现在可行。

答案 4 :(得分:4)

是的,启用像@Martin这样的会议。但是,如果您使用的是Express 4. *版本,则不会捆绑像会话这样的中间件,因此您需要单独安装它。

  1. 在package.json
  2. 中添加"express-session": "1.4.0"
  3. npm install
  4. 使用它
  5. var express = require('express');
    var cookieParser = require('cookie-parser')
    var session = require('express-session')
    var app = express()
    app.use(cookieParser()) // required before session.
    app.use(session({secret: 'keyboard cat'}))
    

    有关详细信息,请查看express session documentation.

答案 5 :(得分:4)

我遇到同样的问题,因为只是复制&粘贴来自快速会话文档的代码,但没有完全阅读文档。

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

在文档中,它提到:

  

但是,它需要启用https的网站,即HTTPS   安全cookie所必需的。如果设置了安全,您可以访问您的   通过HTTP站点,不会设置cookie。

因此,如果您只有HTTP连接,请删除安全选项,以下代码应该有效:

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  //cookie: { secure: true } remove this line for HTTP connection
}))

答案 6 :(得分:3)

在路线中,请尝试添加:{session: true}

app.get('/auto-login', passport.authenticate('cross', {session: true}))

答案 7 :(得分:3)

我使用快递4时遇到了同样的问题,在尝试了几乎我能在网上找到的所有内容后,我终于通过添加“cookie-session'”来设法让它发挥作用。

var cookieSession = require('cookie-session');

app.use(cookieSession({
  keys: ['key1', 'key2']
}));

答案 8 :(得分:1)

'req.user' 仅在passport.auth 中间件之后才为我设置为用户。我来到这个线程试图找出如何从其他请求(没有passport.auth中间件)访问用户名,如果其他人被困在这个问题上,那么试试

req._passport.session.user;

答案 9 :(得分:1)

我认为每个人在服务器端都有一些错误,可能会导致此问题。

要解决此错误,请检查以下内容:

检查1-护照序列化和反序列化

正确的方法(猫鼬):

passport.serializeUser((user, done) => {
    done(null, user._id);
});

passport.deserializeUser((_id, done) => {
  User.findById( _id, (err, user) => {
    if(err){
        done(null, false, {error:err});
    } else {
        done(null, user);
    }
  });
});

检查2-会话

检查您的 cookie-session 程序包是否已正确配置并且可以正常工作。检查您是否真的可以在客户端看到cookie。如果您使用的是 express-session ,请确保可以在内存或缓存(Redis)中看到session-id。

检查3-SSL nginx

确保您的反向代理支持cookie和请求类型。不要忘记检查cookie /会话配置[secure标志]

遇到此错误时,我正在使用 (user) 作为回调函数。然后,我用 (err, user) 进行了更正。现在没事了。干杯?

答案 10 :(得分:1)

当您在客户端使用http请求时,请记住附加凭据。 在Angular2中,您需要添加选项参数:{withCredentials:true}。在此之后,您将拥有相同的req.sessionID,直到您再次重置它。

this._http.get("endpoint/something", { withCredentials: true })

答案 11 :(得分:1)

一旦设置了快速会话,请确保您拥有护照序列化&反序列化,在生成req.user时的反序列化函数中。请参阅另一个stackoverflow问题中的解释here

passport.serializeUser(function(user, done) {
 done(null, user);
});


passport.deserializeUser(function(user, done) {
 done(null, user);
});

答案 12 :(得分:1)

我的是饼干& CORS。 我通过将以下代码添加到我的服务器来解决:

allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // your website
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if ('OPTIONS' === req.method) {
    res.send(200);
} else {
    next();
}};

答案 13 :(得分:0)

有完全相同的问题。对我来说,解决方案是使用"客户端会话"而不是' express-session"。可能是糟糕的会话配置?

不工作代码:

var session = require('express-session');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(session({
    secret: 'random string',
    resave: true,
    saveUninitialized: true,
    cookie: { secure: true }
}));

工作代码:

var session = require('client-sessions');

        app.use(bodyParser.urlencoded({ extended: false }));
        app.use(express.static(path.join(__dirname, 'public')));
        app.use(cookieParser());
        app.use(bodyParser.json());
        app.use(session({
        cookieName: 'session',
        secret: 'random string',
        duration: 30 * 60 * 1000,
        activeDuration: 5 * 60 * 1000,
    }));

答案 14 :(得分:0)

我在req.isAuthenticated()和req.user中都遇到了相同的问题,这是我的解决方法

  • req.isAuthenticated() 通过在deserialize()内的findById()方法中用find()替换findOne()来解决,然后我可以保存经过身份验证的请求,否则将不返回任何内容。

  • req.user 通过调整顺序解决,应该先存储快速会话,然后初始化护照,然后将下一个会话存储在passport.session()中,然后在将会话保存在passport.session()中之后,我们可以访问req.user

app.use(session(...));
app.use(passport.initialize());
app.use(passport.session());
// Now we can access req.user so after we will call req.user, if we write it above these, it will always return underfined
app.use(function(req, res, next){
  res.locals.user = req.user || null
  next();
})

请参见,如果您要在passport.session()之后访问req.user,请在下面添加路由。

答案 15 :(得分:0)

在进行session: true时,您可以添加app.post("/login", passport.authenticate('local', { 'failureRedirect': '/login', 'session': true }), (req, res)=>{ res.redirect("/"); }); 来解决您的问题:

class Person extends Component {
    render() {
        return (
            <div onClick={this.propes.onClick}>{this.props.children}</div>
        )
    }
}

答案 16 :(得分:0)

我的与所有这些都不一样。我以前曾在localhost上开发一个Wordpress站点,然后切换到一个单独的Node / React项目。

由于两个项目都在本地主机上运行,​​因此来自Wordpress网站的cookie仍然存在并正在发送。这就是问题所在。

我必须清除本地主机的cookie,然后它才能工作。

答案 17 :(得分:0)

我的两分钱: 无效的代码:

poll

工作代码:

server.use(
session({
  secret: "secretsssss",
  rolling: false,
  resave: false,
  saveUninitialized: false,
  cookie: {
    sameSite: true, //this line
    maxAge: 60 * 60 * 1000
  }
})
);

答案 18 :(得分:0)

对用户进行身份验证时,将填充请求值req.user。要知道是否标识用户并填写该值,将使用cookie。 如果像我一样,您使用安全cookie配置会话,则cookie仅在HTTPS上可用,这不是本地开发服务器的标准配置。要使Cookie在HTTP上正常运行,请注释掉cookie: { secure: true },并正确配置req.user的值:

this.app.use(session({
    resave: true,
    saveUninitialized: true,
    secret: process.env.SESSION_SECRET || "a secret",
    // cookie: { secure: true },
}));

如果合理地说,您只想在生产中使用Cookie超过HTTPS,则可以执行以下操作:

cookie: { secure: process.env.ENV === 'PRODUCTION' }

答案 19 :(得分:0)

服务器发送SetCookie标头,然后通过浏览器句柄存储它,然后将Cookie与在HTTP HTTP标头内向同一服务器发出的请求一起发送。

我必须在客户端中设置withCredentials:true。 (axios.js)

const config = {
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
  },
};

axios.put(url, { page: '123' }, config)
  .then(res => console.log('axios', res))
  .catch(err => console.log('axios', err));

然后发生CORS问题。

因此我将其添加到我的快递服务器中:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  if ('OPTIONS' == req.method) {
    res.send(200);
  } else {
      next();
  }
});

答案 20 :(得分:0)

您是否曾尝试在cookieParser中插入您的secretKey?

var passport = require('passport');
var expressSession = require('express-session');

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('mySecretKey'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressSession({
secret: 'mySecretKey',
  resave: false,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

答案 21 :(得分:0)

遇到了同样的问题,但是我的原因更多是与误解passport.authorizepassport.authenticate在OAuth流和OAuth回调路由开始时的差异有关。

passport.authorize不会影响req.user变量,但是由于我只是复制并粘贴了该策略文档中的示例代码,所以我没有意识到使用了错误的方法。更改为passport.authenticate后,用户变量可用。

希望这可以帮助在不知不觉中做同样事情的人。

答案 22 :(得分:0)

更改顺序:

app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));

对此:

app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");

答案 23 :(得分:0)

我在将cookie解析器与express-session一起使用时是这样的:

var express = require("express"); // 4.16.1
var cors = require("cors"); // 2.8.5
var cookieParser = require("cookie-parser"); // 1.4.4
var expressSession = require("express-session"); // 1.17.1

var app = express();

app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
);

app.use(express.json());
app.use(express.urlencoded({ extended: true }));


app.use(
  expressSession({
    secret: "secret123",
    resave: true,
    saveUninitialized: true,
    cookie: { maxAge: 60 * 60 * 24 * 1000 },
  })
);
app.use(cookieParser("secret123")); // this line

在快速会话之前放入cookie解析器对我有用,就像这样:

var express = require("express"); // 4.16.1
var cors = require("cors"); // 2.8.5
var cookieParser = require("cookie-parser"); // 1.4.4
var expressSession = require("express-session"); // 1.17.1

var app = express();

app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
);

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(cookieParser("secret123"));
app.use(
  expressSession({
    secret: "secret123",
    resave: true,
    saveUninitialized: true,
    cookie: { maxAge: 60 * 60 * 24 * 1000 },
  })
);

答案 24 :(得分:0)

如果你的中间件堆栈不清楚,假设你有会话中间件某处,你可以在重定向之前保存会话:

if (req.user) {
    req.session.save(function (err) {
        if (err) {
            // ... panic!
        }
        res.redirect("/user/" + req.user._id);
    });
    return;
}

答案 25 :(得分:-1)

我有一个不同的问题,有bcrpt-node和arrow函数。

有效的代码:

userSchema.methods.generateHash = function (password) {
  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); 
};

userSchema.methods.isValidPassword = function (password) {
  return bcrypt.compareSync(password, this.password);
};

不起作用的代码:

userSchema.methods.generateHash = (password) => {
  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

userSchema.methods.isValidPassword = (password) => {
  return bcrypt.compareSync(password, this.password);
};