使用节点 js、AngularJs 和 JWT 使用用户名和密码进行身份验证

Authentication with username & password with node js, AngularJs and JWT

我正在创建生产 angularJs 应用程序。

现在我已经创建了我的部分 RESTFul API

这个 API 在登录时生成 user object 但是我不热衷于通过 HTTP header 发送 password 未散列/未加密的.

让您对我的 API 有一些了解:

登录时:

    var jwt = require('jwt-simple');

// Route: /login
module.exports = function (express, sequelize, router) {

    var DataTypes = require("sequelize");
    var crypto = require('crypto');

    var User = sequelize.define('user', {
            id: DataTypes.INTEGER,
            username: DataTypes.STRING,
            name: DataTypes.STRING,
            organization_id: DataTypes.INTEGER,
            type_id: DataTypes.INTEGER,
            division_id: DataTypes.INTEGER
        }, {
            freezeTableName: true,
            instanceMethods: {
                retrieveByNamePassword: function (username, onSuccess, onError) {
                    User.find({where: {username: username}}, {raw: true})
                        .then(onSuccess).catch(onError);
                }
            }
        }
    );

    router.route('/login')

        .post(function (req, res) {
            var user = User.build();

            var username = req.body.username || '';
            var password = req.body.password || '';

            if (username == '' || password == '') {
                res.status(401);
                res.json({
                    "status": 401,
                    "message": "Invalid credentials"
                });
                return;
            }

            user.retrieveByNamePassword(username, function (users) {
                if (users) {
                    // If authentication is success, we will generate a token
                    // and dispatch it to the client
                    res.json(genToken(users));
                    return;
                } else {
                    // If authentication fails, we send a 401 back
                    res.status(401);
                    res.json({
                        "status": 401,
                        "message": "Invalid credentials"
                    });
                    return;
                }
            }, function (error) {
                res.status(401);
                res.json({
                    "status": 401,
                    "message": "Invalid credentials"
                });
                return;
            });
        });

    var genToken = function(user) {
        var expires = expiresIn(7); // 7 days
        var token = jwt.encode({
            exp: expires,
            user_id: user.id,
            organization_id: user.organization_id,
            type_id: user.type_id,
            division_id: user.division_id

        }, require('./config/secret')());

        return {
            token: token,
            expires: expires,
            user: user
        };
    };

    var expiresIn = function(numDays) {
        var dateObj = new Date();
        return dateObj.setDate(dateObj.getDate() + numDays);
    };

正如您现在看到的(因为我还不确定如何处理它)我只是在寻找用户名,然后检查用户名是否存在。

我的问题很简单,您如何加密密码,然后在密码到达 API 时对其进行验证?

JWT 可用于加密和非加密数据。然而,无论您是否对正在传输的信息进行加密,总会涉及一个签名过程,它允许您在阅读之前验证您收到的信息未被篡改。

对于通过 URL 在域之间传输登录状态的用例,我会说 根本不包括密码 在你的 JWT 中将是最好的选择.

以下面的流程为例:

  1. POST 您通过 HTTP 登录域 1 的详细信息。
  2. 验证用户。如果成功,创建至少包含以下内容的 JWT:

    2.1。 exp:到期时间(假设当前时间+最多10到15秒)

    2.2。 iat:令牌创建时间

    2.3。 email: 用户的电子邮件地址

    2.4。 不要包含用户密码(或任何其他敏感数据)。

  3. 使用 URL

  4. 中的 JWT 令牌将您的用户重定向到您的域2
  5. 你的另一个server/domain可以检查JWT签名、iat和exp时间来验证JWT没有被篡改并且是有效的。
  6. 如果全部有效,请将您的用户登录到其他域。

这是有效的,因为只要 JWT 数据通过验证,第二个域实际上不需要知道您的用户密码,因为 domain1 服务器已经验证了登录并且只是告诉 domain2 接受它。只要您的 JWT 密钥保持 完全保密 ,这应该是相当安全的。 如果可能的话,我也鼓励使用自动方法定期随机更改两台服务器上的密钥。

注意:使用此方法,任何获得 JWT 的人都可以查看其中包含的数据 - 所以不要在那里传输任何机密或敏感信息。

注意 2:无论您在 JWT 的到期字段中设置什么时间段,此方法都容易受到重放攻击。如果第三方可以在该时间段内获得令牌,他们也可以使用令牌以该用户身份登录。出于这个原因,您必须将到期字段保持在尽可能低的位置以降低这种风险。

这太晚了,但是你能不能在使用 crypt 的用户模型之后添加一个钩子? (像这样:https://www.youtube.com/watch?v=pquxHIBx8ks

// User model...
},   {
hooks: {
    beforeValidate: function() {

    },
    afterValidate: function(User) {
        User.hashword = bcrypt.hashSync(User.hashword, 10);



    },
    beforeCreate: function() {

    },
    afterCreate: function() {

    }
}
});