这很奇怪.Im Passport的"本地策略"为我的快递应用而且我遇到了一个奇怪的问题.
基本上,我有三条路线.每个人都有一个auth检查到位.
app.get('/admin', authenticatedOrNot, adminRoute.index);
app.get('/admin/new', authenticatedOrNot, adminRoute.newpost);
app.post('/admin/new', authenticatedOrNot, adminRoute.create);
Run Code Online (Sandbox Code Playgroud)
authenticatedOrNot方法很简单:
var authenticatedOrNot = function(req, res, next){
if(req.isAuthenticated()){
next();
}else{
res.redirect("/login");
}
}
Run Code Online (Sandbox Code Playgroud)
适用于登录管理区域,并检查用户是否已登录,但是当我将表单提交到'/ admin/new'Post路由时,浏览器挂起.即使使用console.log,控制台也没有任何反应:
exports.create = function(req, res){
console.log(req);
// Database logic here
res.redirect('/admin');
}
Run Code Online (Sandbox Code Playgroud)
我似乎无法让它工作.它只是挂起,最终失败了.浏览器控制台只是在网络请求中说"待定".
香港专业教育学院尝试从后期路线和相同的问题中删除'authenticatedOrNot'方法,但如果我删除所有三个它工作正常.
我很难过.
有帮助吗?其他人遇到这个?
之前没有注意到这一点,因为对于客户端 - 服务器通信,不需要通过XHR进行身份验证(截至目前).在实现一些集成测试时,我正在创建realy请求node-xmlhttprequest到应用程序的实际实例.用户在第一个请求中进行身份验证,理论上用户的唯一标识符和一些其他相关信息存储在会话中(正如我所说,这对真正的客户来说很好,他们不需要通过XHR确认他们的身份).出于某种原因,即使使用完全相同的会话ID触发后续请求,我也无法在后续请求中检索会话,因此无法看到用户已通过身份验证,这会导致测试失败预期的行为不会发生,HTTP 401 UNAUTHORIZED正在填满终端.
我已经看到了几个看起来像这样的问题,但是"相同的会话ID"似乎并不存在.
我是否需要手动将Set-Cookie标头添加到所有XHR请求中?那太可怕了,必须有更好的方法!
所以人们喜欢源代码,这里有一些来自测试,解雇这些请求:
// Ensure logged in before sending request, to verify that authorized
// users encounter the expected behaviour.
jQuery.post(domain+'/login', {email:'test@express.app', password:'12345678'},
function(data,x,y){
data.should.equal("true")
jQuery.ajax({url:domain+'/event', type:"POST",
name: "TestEvent", location: "TestVille",
startDate: new Date('2013-09-01'), startTime: '6:45 pm',
description: "Test Event #1", success: state.success,
error: state.error, completed: state.completed
})
})
Run Code Online (Sandbox Code Playgroud)
登录发生,用户ID被写入会话(`req.logIn()应该这样做,并且它不报告任何失败),用户ID的序列化不报告任何失败,我非常困惑为什么后续使用相同会话ID的请求无法找到序列化的用户ID.
我一般不参与网页开发,所以对某些人来说这可能是显而易见的,但我一直在寻找一个答案而根本找不到答案.我很感激任何指针,我很乐意提供尽可能多的代码,以说明问题所在.
可能相关的一些额外代码点:
用户ID的序列化/反序列化(目前以最简单的方式实现 - 在初始化中间件之后,在初始化护照和passpot.session()之后很早.这非常适用于非XHR请求)
// Serialize user for passport session-store
// Currently only serializing 'user_id'
passport.serializeUser(function(user, done) {
done(null, user._id)
})
// Deserialize user …Run Code Online (Sandbox Code Playgroud) [Error: data and hash arguments required]尝试在我的节点应用程序中验证用户的现有密码时出现错误.上下文是我要求我的用户在用户个人资料页面中更改之前验证他们的现有密码.我的堆栈是node + mondodb(通过mongoose)使用passport-local和bcrypt.
相关代码是:
// code trying to match that returns the aforementioned error
req.user.comparePassword(req.body.password, function (err, isMatch) {
if (err) {
return console.error(err);
}
if (isMatch) {
console.log('passwords match');
// now save new password
// Password verification
userSchema.methods.comparePassword = function (candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
}
}
Run Code Online (Sandbox Code Playgroud)
req.user引用当前用户对象,`req.body.password'是从用户的POST获得的密码.我在这里使用护照本地示例中的UserSchema,护照策略和Bcrypt配置.
有人可以提供有关如何在更新之前验证密码是否匹配的指导?
我有一个 NodeJs REST 服务,我们称之为 -后端的NodeRest和前端的 AngularJs。
NodeRest应该与移动应用程序以及 Web 应用程序一起使用,在我的情况下它是 AngularJs 应用程序。
NodeRest 的架构在使用 PassportJs 时应该解决以下问题:
服务器不应将用户重定向到 Facebook 以在何时进行授权
app.get('/auth/facebook', passport.authenticate('facebook'));
Run Code Online (Sandbox Code Playgroud)
已被调用。
如果它要重定向它,客户端将不会得到任何东西,因为回调 url 链接到NodeRest httpL//noderest/facebook/callback。相反,它应该提供重定向 uri,以便我可以将其发送回客户端(angularJs、mobile 等...)。像这样:
app.get('/auth/facebook', passport.authenticate('facebook', function(redirectUri){
//emit socket event to the client with redirect uri as a response data. }));
Run Code Online (Sandbox Code Playgroud)
我决定在授权过程中使用 socket.io 作为通信渠道。
客户:
var socket = io.connect(baseUrl);
socket.on('auth:facebook:callback:getCalled', function (data) {
// callback get called on server side.
// user has been authenicated.
// so now, user can talk with our …Run Code Online (Sandbox Code Playgroud) 我使用PassportJS和ExpressJS.我有一条路线logout:
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
Run Code Online (Sandbox Code Playgroud)
但是,当使用浏览器的后退按钮时,仍然可以显示仅供登录用户使用的页面.如何避免上述情况?谢谢
我正在使用PassportJS本地策略进行用户身份验证,它的工作完全正常.但是,当我在任何经过身份验证的页面上尝试console.log(req.user)时,我会获得当前登录用户的所有数据库条目详细信息.这是正常的吗?包括哈希密码
{
name: 'Test',
email: 'vxxxxx@gmail.com',
password: '$2a$10$aw2aMtXtrmKHi.kd97c0NeMOu6Y0hlcM4xk2VuqfneLYdEkc676eq',
phone: 9xxxxx6,
_enabled: true,
_id: 5253f326003e55f028000001,
__v: 0
}
Run Code Online (Sandbox Code Playgroud)
我的本地策略定义如下.
passport.use(new strategy(function(username, password, done) {
User.findOne({ "email": username }, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
if(user._enabled==false) return done(null,false,{message: "Dear "+user.name+", Please verify your email first!"});
if(bcrypt.compareSync(password,user.password)){
return done(null, user);
app.set("userEmail",username);
}
else {
return done(null, false, { message: 'Invalid password' });
}
db.close();
}) …Run Code Online (Sandbox Code Playgroud) 我想知道如何(如果可能的话)可以从Facebook获得持久性令牌,因为来自Passport的身份验证只提供了一个短时令牌(从我读到的内容).如果可以,我会知道如何让用户在重新连接到我的网站时仍然登录.这是我的(但不是非常一致)代码:
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy;
var express = require('express'),
app = express();
passport.use(new FacebookStrategy({
clientID: "xxxxx",
clientSecret: "xxxxxx",
callbackURL: "/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done)
{
done(null, profile);
}
));
app.get('/login', function(req, res)
{
res.end('<a href="/auth/facebook">Login with Facebook</a>') ;
})
app.get('/', function(req, res)
{
res.end('logged in !') ;
})
app.get('/auth/facebook', passport.authenticate('facebook', { scope: ['user_event'] }));
app.get('/auth/facebook/callback',
passport.authenticate('facebook', { successRedirect: '/',
failureRedirect: '/login' }));
var server = app.listen(8080);
Run Code Online (Sandbox Code Playgroud) 在各种情况下,Facebook的内部AccessToken(用于Facebook API中的各种功能和其他情况)可能会变得无效.例如,如果用户在使用依赖Facebook登录的应用程序的会话之间更改其密码.还有一些其他案例.
但是,会发生什么情况,您的应用程序基本上崩溃,出现如下错误:data={"error":{"message":"Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.", "type":"OAuthException", "code":190, "error_subcode":460}}.
Passport的Facebook策略使用AccessToken,只要用户通过Passport登录/验证,它就可用于应用程序.但问题是遇到上述错误时该怎么办.Facebook在PHP中给出了一个复杂的重新认证流程,但一般意义上说你需要用Facebook重新授权你的应用程序.
问题是,即使从Facebook页面删除Facebook应用程序,并迫使依赖Facebook登录的应用程序重新授权,似乎Passport + Facebook策略仍然从浏览器的会话存储中获取最后一个现有的AccessToken.(至少那是我在Mozilla/Fx 26上看到的).我已经多次重新授权我的应用程序了,但是在调试并查看Passport返回的内容时,我总是找回相同的无效AccessToken.看起来如果会话存储中存在AccessToken,Passport就会选择它,而不是从Facebook获取新的.
那么有没有办法 - 在Passport + Facebook策略中 - 基本上忽略或覆盖任何存储的AccessToken并且总是在Facebook发出新的请求,如果出现这种错误?根本不清楚如何实现这一点.谢谢您的帮助.
更新:调用策略的示例代码refreshToken作为参数; 这是做什么的?这个参数有可能的解决方案吗?
passport.use(new FacebookStrategy(
{
...
},
function(accessToken, refreshToken, profile, done)
{
Run Code Online (Sandbox Code Playgroud) 我已经能够使用Passport进行身份验证,但我不知道如何访问序列化用户.我已经在几个地方读过访问它的方法是使用req.user但是当我尝试使用GET到/ hello时,它表示用户未定义...
这是我的app.js
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var authentication = require('./routes/authentication');
var content = require('./routes/content');
var posts = require('./routes/post.js');
var upload = require('./routes/upload.js');
var media = require('./routes/media.js');
var http = require('http');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var mongoConnectionString = 'mongodb://localhost/judgmental';
var User = require('./models/user.js');
mongoose.connect(mongoConnectionString, function(error) {
if (error) {
throw error;
}
console.log('Successfully connected to MongoDB');
});
var app = …Run Code Online (Sandbox Code Playgroud) 当我尝试使用angular.js的$ http模块来授权twitter应用程序时,我总是得到:
XMLHttpRequest cannot load https://api.twitter.com/oauth/authenticate?oauth_token=something. Origin null is not allowed by Access-Control-Allow-Origin.
Run Code Online (Sandbox Code Playgroud)
客户代码:
$http({
method: 'GET',
headers: { "Content-Type": undefined },
url: '/oauth/twitter'
});
Run Code Online (Sandbox Code Playgroud)
服务器代码:
app.configure(function () {
app.use(express.cookieParser());
app.use(express.cookieSession({ secret: 'tobo!', cookie: { maxAge: 3600 }}));
app.use(express.session({secret: 'secret'}));
app.use(passport.initialize());
app.use(passport.session());
});
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers",
'Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept');
next();
});
app.get('/oauth/twitter', passport.authenticate('twitter'), function (req, res) {
// The request will be redirected to Twitter for authentication, so this …Run Code Online (Sandbox Code Playgroud)