2015-01-19 2 views
4

Я делаю приложение с экспресс-паспортом и угловымJS; Я хочу иметь возможность отправлять любые ошибки, возникшие из паспорта (например, имя пользователя, полученное или не отправленное по электронной почте) json, поэтому мое приложение angularJS может получать эти ошибки в ответ json. Более конкретно, прямо сейчас я хочу ответить json на мой метод POST регистрации, который выводит любые ошибки. Я попытался сделать это для себя, и я ищу по всему Интернету и переполнению стека, я просто не могу это решить!Ошибка отправки паспорта json

Вот мой файл пользователей маршрут экспресс:

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

Я знаю, глядя на мой код прямо сейчас, похоже, я не пробовал самостоятельно решить это, но это всего лишь мой последний рабочий код; Я застрял в этом в течение последних нескольких дней!

Любая помощь будет принята с благодарностью :)

ответ

2

В соответствии с действующим кодом паспорта это, вероятно, достижимо путем пропускания обратного вызова для обработки всех результатов authentiction самостоятельно. Этот обратный вызов предоставляется после опций или вместо них.

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

или

passport("local-login", callbackFn); 

Этот обратный вызов используется в все результирующие ситуации пытаться authenticae. Таким образом, вызывается обработки ошибок, как это:

callbackFn(err) 

Если (все сконфигурированные) аутентификации не удалось его называют с

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

Успешно того заверенного пользователя обратного вызова вызывается следующим образом:

callbackFn(null, user, infos) 

с infos опционально предоставляется стратегиями.

Сейчас идет снизу сторону: В либо ситуации passport.authenticate() пропускает обычную обработку, но сразу же вызывает функцию обратного вызова для ухода за остальные. Это включает в себя обработку любых опций, переданные в вызове для passport.authenticate() как мигания сообщений, подготавливая сессии и запрос, содержащую аутентификацию пользователя и т.д.

  1. Поскольку параметры, приведенные passport.authenticate() никогда не передаются в функции обратного вызова нет фактически никакой очевидной причины использовать оба.
  2. Когда я наткнулся на ту же проблему (связывая паспорт-сервис с запросом POST с угловым js), я отказался рассматривать возможность использования обратного вызова надлежащего решения. Этот обратный вызов не документирован. И это даже не выглядит весьма полезным, поскольку он не пропускает req, res и next, чтобы передать любой фактический запрос в обратном вызове. Таким образом, совсем не имеет смысла использовать его вообще, и я ожидаю, что он скоро исчезнет или изменит его поведение.

Итак, второй подход состоял в попытке выяснить, почему существует проблема в AngularJS. Паспорт отправляет простой текст Unauthorized в ответ со статусом 401. AngularJS пытается разобрать это как JSON и производит синтаксическую ошибку. Текст Unauthorized результаты passprt заканчивающиеся ответ очень просто, вызывая

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

Таким образом, собственно обходной путь может попытаться заменить

  1. либо текст в http.STATUS_CODES, хотя это оказывает влияние на обработку дополнительных запросов и, следовательно, не является предпочтительным
  2. или res.end() перегруженным способом, действующим по-другому, если res.statusCode - 401.

Из-за воздействия на любой текущий запрос, только я пробовал последний. Заменено 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); 
    } 
); 

Наконец, любой подход действительно является обходным путем. Я считаю, что паспорт нуждается в пересмотре этого раздражающего ограничения.

Смежные вопросы