我正在制作带快递+护照和angularJS的应用程序;我希望能够通过json发送护照产生的任何错误(例如用户名或不提供电子邮件),这样我的angularJS应用程序就可以在json响应中收到这些错误。现在更具体地说,我想对我的注册POST方法进行json响应,输出任何错误。我试图为自己做这个,我在网上搜索和堆栈溢出我无法解决这个问题!
这是我的用户路由文件在express:
var express = require('express');
var router = express.Router();
var isAuthenticated = require('../config/isAuthenticated');
module.exports = function(passport){
router.get('/loggedin', function(req, res){
res.send(req.isAuthenticated() ? req.user : '0');
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/',
failureRedirect : '/signup',
failureFlash: true
}));
router.post('/login', passport.authenticate('local-login'), function(req, res){
res.send(req.user);
});
router.post('/signout', function(req,res){
req.logout();
res.json({redirect: '/'});
});
router.get('/authtest', isAuthenticated, function(req, res){
res.render('authtest', {user: req.user});
});
return router;
};
这是我的护照注册策略:
passport.use('local-signup', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password, done){
process.nextTick(function(){
User.findOne({'local.username' : username}, function(err, user){
if(err) return done(err);
if (user) { //username already exists
return done(null, false, {message: 'Username already exists'});
} else if(!req.body.email) { //no email address provided
return done(null, false, {message: 'You must provide an email address!'});
} else {
var newUser = new User();
newUser.local.username = username;
newUser.generateHash(password, function(err, hash){
if(err) return done(err);
newUser.local.password = hash;
});
newUser.email = req.body.email;
newUser.servers = [];
newUser.save(function(err){
if(err) throw err;
return done(null, newUser);
});
};
});
});
}
));
我知道现在看着我的代码看起来我自己都没有试过解决这个问题,但这只是我最新的工作代码;过去几天我一直被困在这里!
非常感谢任何帮助:)
答案 0 :(得分:2)
根据目前的护照代码,这可能是通过传递自定义回调来自己处理所有真实结果而实现的。这个回调是在选项之后给出的,而不是那些。
passport( "local-signup", { ... }, callbackFn );
或
passport( "local-login", callbackFn );
此回调用于尝试验证的所有结果情况。因此,它会在处理错误时调用:
callbackFn( err )
如果(所有已配置)身份验证失败,则使用
进行调用callbackFn( null, false, challenge(s), status(es) )
成功通过身份验证的用户后,将调用回调:
callbackFn( null, user, infos )
可选择由策略提供infos
。
现在来到底层:在 情况passport.authenticate()
跳过正常处理但立即调用提供的回调以关注其余部分。这包括处理呼叫passport.authenticate()
时传递的任何选项,如闪烁消息,准备会话和请求包含经过身份验证的用户等。
passport.authenticate()
的选项永远不会传递给回调,因此实际上没有明显的理由同时使用它们。req
,res
和next
来传递回调中的任何实际请求。因此,使用它几乎没有任何意义,我希望它很快就会消失或者改变它的行为。所以第二种方法是试图找出AngularJS中存在问题的原因。 Passport正在发送纯文本Unauthorized
以回复状态代码401
。 AngularJS试图将其解析为JSON并产生语法错误。文本Unauthorized
来自passprt结束响应非常简单地通过调用
res.statusCode = 401;
res.end(http.STATUS_CODES[res.statusCode]);
因此,正确的解决方法可能会尝试替换
http.STATUS_CODES
中的任何一个文字虽然这对处理更多请求产生了影响,因此并不是优先考虑的res.end()
为401,res.statusCode
通过重载方法采取不同的行为。由于影响了当前的任何请求,我尝试了后者。替换res.end()
可能用于发送您想要的任何文本:
router.post('/login',
function(req, res, next) {
var _end = res.end;
res.end = function() {
if (res.statusCode === 401) {
return _end('{"status":"Unauthorized"}');
}
return _end.apply(this, arguments);
};
next();
},
passport.authenticate('local-login'),
function(req, res) {
res.send(req.user);
}
);
或者,替换方法可能会在内容类型上添加以前缺少的响应头信息,因为这实际上导致AngularJS处理中的问题,默认情况下响应为JSON 。
router.post('/login',
function(req, res, next) {
var _end = res.end;
res.end = function() {
if (res.statusCode === 401) {
res.set("Content-Type", "text/plain");
}
return _end.apply(this, arguments);
};
next();
},
passport.authenticate('local-login'),
function(req, res) {
res.send(req.user);
}
);
最后,任何一种方法都只是一种解决方法。我认为护照需要修改这个恼人的限制。