AngularJS+Satellizer+Node.js+MongoDB->Instagram-13

Build an Instagram clone with AngularJS, Satellizer, Node.js and MongoDB

13.Login 和 Signup 的 Express 路由

我们的 Login路由非常简单。它要做的仅仅是认证 email 和 password。如果两个都正确了,那么就返回一个新的令牌和用户对象。

把下面的路由接着加到我们上次的地方,在 isAuthenticated() 的后面。

<!-- lang: js -->
app.post('/auth/login', function(req, res) {
  User.findOne({ email: req.body.email }, '+password', function(err, user) {
    if (!user) {
      return res.status(401).send({ message: { email: 'Incorrect email' } });
    }

    bcrypt.compare(req.body.password, user.password, function(err, isMatch) {
      if (!isMatch) {
        return res.status(401).send({ message: { password: 'Incorrect password' } });
      }

      user = user.toObject();
      delete user.password;

      var token = createToken(user);
      res.send({ token: token, user: user });
    });
  });
});

在查询中的 +password 参数告诉 Mongoose 结果中包含 password 字段。我们必须这样做,因为之前已经明确告诉 Mongoose 把 password 字段从所有查询结果的用户模型中去掉,通过设置 password: { type: String, select: false }

还记得我们在 Step 9 中创建 User 模型的时候,是怎样用 bcrypt 来做 password 字段的 hash 的吗?你看,我们检查两个密码是否匹配的时候,不能简单的用两个字符串来比较,需要用 bcrypt.compare() 。为了更好的说明这一点,看一下 bcrypt 文档的这个例子:

<!-- lang: js -->
var hash = bcrypt.hashSync("bacon");

bcrypt.compareSync("bacon", hash); // true
bcrypt.compareSync("veggies", hash); // false

如果用户给的 email 是存在的,并且密码也正确, 在 第 12-13 行 我们把 Mongoose Document object 转成纯 JavaScript 对象,然后删掉 password 属性。你可能会想知道为什么不直接删除 password 属性,还要先来一次转换。

事实上,Mongoose 返回的文档对象是不可辨的,所以即使你删掉 password 属性也改变不了什么。但是,你可以,通过在 Mongoose 查询中通过更详细的参数配置,也能达到同样的目的。不管哪种方法,对我们的结果都好用。

以这种方式创建 Incorrect email and Incorrect password 异常信息的原因,不单是要在 login form 上显示验证异常。这和通常的 form 把所有的异常都一溜显示出来的做法不同,异常信息会独立的现实在每个 form 字段下面。

https://hackhands.com/wp-content/uploads/2014/10/Screenshot-2014-10-27-00.32.32.png

然后是 signup 的路由。首先它检查是否输入了 email (不能有重复的 email)。然后它用 bcrypt 把 password 哈希之后保存到数据库。

signup 路由的代码如下:

<!-- lang: js -->
app.post('/auth/signup', function(req, res) {
  User.findOne({ email: req.body.email }, function(err, existingUser) {
    if (existingUser) {
      return res.status(409).send({ message: 'Email is already taken.' });
    }

    var user = new User({
      email: req.body.email,
      password: req.body.password
    });

    bcrypt.genSalt(10, function(err, salt) {
      bcrypt.hash(user.password, salt, function(err, hash) {
        user.password = hash;

        user.save(function() {
          var token = createToken(user);
          res.send({ token: token, user: user });
        });
      });
    });
  });
});

注意: 该路由只负责通过 email 和 password 的 signup 处理。通过 Instagram 认证来创建一个新的账号,这是另一条完全不同的路由。

你可能感兴趣的:(AngularJS,express,nodejs,node,node.js,OAuth,oauth2,Satellizer,OAuthn)