如何使用passportjs的jquery / ajax数据

时间:2014-09-24 14:50:37

标签: javascript jquery ajax node.js passport.js

如果我使用表单字段action="/login", method="post"发送登录请求,它可以正常工作。与可用代码herehere类似。

但如果相反,如果我使用jquery/ajax发送相同的信息,那么护照似乎不起作用。没有通过护照进行实际登录,但是ajax调用会给出一个误导性的成功消息。

以下不起作用。虽然我收到“登录成功”消息,但登录并没有真正发生。

$('#login_button').click(function () {

    var email = $('#email').val();
    var password = $('#password').val();
    alert ('email/pass:' + email + ", " + password);

    $.ajax({
        type: "POST",
        url: "/login",
        data: { email: email , password: password },
        dataType: 'html'
    })
            .done(function () {
                console.log("http request succeeded");
                alert("login success");
            });
});

我需要使用ajax方法,以便在成功登录后我可以在客户端做一些有用的事情。例如。开始socket.io

请帮忙。我的修改后的代码可在此处找到:my-modified-code

3 个答案:

答案 0 :(得分:5)

我尝试了你的代码和Passport-wise它的工作原理。我做了#34; Local Signup"," Logout",然后" Local Login"并且已成功通过身份验证,但在UI中未显示任何内容。

这与您正在讨论的302相关 - 服务器回复302,因为您已定义successRedirect : '/profile',然后jQuery跟随重定向并收到无法解析的HTML,因为它需要JSON。由于您在.fail()电话中未定义$.ajax个回拨,因此您无法看到它。

会话很好,但可以通过手动转到/profile来查看。

当您使用常规HTML表单登录时,浏览器将发送单个HTTP请求并根据响应进行操作(例如,呈现HTML页面,或者如果它是302则执行重定向)。当你调用$.ajax时,同样的情况发生在不同的上下文中 - AJAX调用遵循重定向,因为它发出了请求,但浏览器没有。

您应该为AJAX和HTML登录使用单独的路由,或使用custom callback并根据req.accepts()确定要返回的内容。

单独的路线可以是例如。

// AJAX logins to this URL, redirect on client side using
// window.location.href if login succeeds
app.post('/login/ajax', passport.authenticate('local-login'));

// HTTP login form send to this URL
app.post('/login', passport.authenticate('local-login', {
  successRedirect : '/profile',
  failureRedirect : '/login',
  failureFlash : true
}));

自定义回调可能是这样的(未经测试):

app.post('/login', function(req, res, next) {
  passport.authenticate('local-login', function(err, user, info) {
    switch (req.accepts('html', 'json')) {
      case 'html':
        if (err) { return next(err); }
        if (!user) { return res.redirect('/login'); }
        req.logIn(user, function(err) {
          if (err) { return next(err); }
          return res.redirect('/profile');
        });
        break;
      case 'json':
        if (err)  { return next(err); }
        if (!user) { return res.status(401).send({"ok": false}); }
        req.logIn(user, function(err) {
          if (err) { return res.status(401).send({"ok": false}); }
          return res.send({"ok": true});
        });
        break;
      default:
        res.status(406).send();
    }
  })(req, res, next);    
});

答案 1 :(得分:1)

如果不查看服务器端代码,以及您使用的是哪种护照策略,任何人都无法判断。例如,本地策略的片段如下所示:

function Strategy(options, verify) {
  // snip 
  this._usernameField = options.usernameField || 'username';
  this._passwordField = options.passwordField || 'password';
  // snip
}
// snip

Strategy.prototype.authenticate = function(req, options) {
  options = options || {};
  var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
  var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);
  // snip

}

您从jQuery传递的字段需要与您在服务器端配置它的方式相匹配,以及该策略正在寻找什么。在这种情况下,如果您使用本地策略而未配置用户名和密码,则会查找要在req.body或req.query中传递的用户名和护照字段。

所以不 - 电子邮件不起作用。但是,您可以通过在选项对象中传入一个覆盖默认用户名的字段来实例化策略,例如,

{
   username: 'email'
}

我之前使用过这个来通过jQuery验证护照:

  var login = function (un, pwd) {

        $.ajax({
            type: "POST",
            dataType: 'json',
            data: { "email": un.val(), "password": pwd.val() },
            url: "/rest/login/?format=json",
            success: function (data) {
                window.location.href = '/somewhereElse'
            }
        });
    }

我怀疑你的dataType需要是' json'不是' html'

答案 2 :(得分:0)

也许这是一个比评论中更好的地方。我几个月前经历过类似的事情,并在这里回答了我自己的问题:

Passport authenticate callback is not passed req and res

基本上我能够使用签名来处理帖子:req,res,next和inside,你用所需的策略调用passport.authenticate。 passport.authenticate不应该(或者至少在我的情况下不会起作用)路由的处理程序

server.post(route, function(req, res, next){

    passport.authenticate('local', function(err, user) {

    })

})

我无法让passReqToCallback选项起作用。