护照通过json发送错误

我正在用express +护照和angularJS做一个应用程序; 我希望能够发送任何由护照产生的错误(如用户名采取或没有提供电子邮件)由JSON所以我的angularJS应用程序可以接收这些错误的JSON响应。 更具体地说,现在我想对我的注册POST方法有一个JSON响应,输出任何错误。 我试图为自己做这个,我search遍及networking和堆栈溢出我只是无法工作了这一点!

这里是我的用户路由文件的快递:

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); }); }; }); }); } )); 

我知道现在看我的代码,看起来我没有试图解决这个问题,但这只是我最近的工作代码; 过去几天我一直被困在这里!

任何帮助将不胜感激 :)

根据当前的护照代码,这可能是通过传递自定义callback来处理所有的authentication结果。 这个callback是在选项之后给出的,而不是那些。

 passport( "local-signup", { ... }, callbackFn ); 

要么

 passport( "local-login", callbackFn ); 

这个callback被用于所有的尝试authentication的情况。 因此在处理这样的错误时被调用:

 callbackFn( err ) 

如果(所有已configuration的)authentication失败,则调用

 callbackFn( null, false, challenge(s), status(es) ) 

成功通过身份validation的用户的callback是这样调用的:

 callbackFn( null, user, infos ) 

infos可选地由策略提供。

现在来自底层:任何一种情况下, passport.authenticate()跳过通常的处理过程,但会立即调用提供的callback来处理其余的事情。 这包括在调用passport.authenticate()传递的任何选项的处理,例如闪烁消息,准备会话和请求包含已validation的用户等。

  1. 由于选项passport.authenticate()永远不会传入callback,实际上没有明显的理由使用两者。
  2. 当我绊倒了同样的问题(链接护照服务与angular-js POST请求)时,我拒绝考虑使用callback一个适当的解决scheme。 这个callback没有logging。 而且它不是非常有用,因为它不传递reqresnext来传递callback中的任何实际请求。 因此,根本没有什么意义,我希望它很快就会消失或者相当多地改变它的行为。

所以第二种方法是要找出为什么AngularJS存在问题。 护照正在发送纯文本Unauthorized响应状态代码401 。 AngularJS试图将其parsing为JSON并产生语法错误。 文本Unauthorized结果来自passprt结束响应,非常简单地通过调用

 res.statusCode = 401; res.end(http.STATUS_CODES[res.statusCode]); 

因此,一个适当的解决方法可能会尝试replace

  1. 或者http.STATUS_CODES中的文本,尽pipe这对处理进一步的请求具有影响,因此不是优选的
  2. 如果res.statusCode是401,那么res.end()通过重载的方法起作用。

由于影响任何目前的要求,只有,我试过后者。 replaceres.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); } ); 

或者,replace的方法可能会添加以前缺less的内容types的响应标头信息,因为这实际上导致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); } ); 

最后,两种方法都只是一种解决方法。 我认为护照是需要修改这个令人讨厌的限制。