使用passportjs重置/更改nodejs中的密码

 书友69391618 发布于 2023-02-13 20:49

我在nodejs中使用passportjs来创建登录系统.一切都很好,但我不知道如何在忘记密码或想要更改密码时重置用户密码.

MongoDB中的用户模型

var UserSchema = new Schema({
    email: String,
    username: String,
    provider: String,
    hashed_password: String,
    salt: String,
});

提前致谢!

2 个回答
  • 我真的不喜欢命中我的数据库来存储令牌,特别是当你想要为许多动作创建和验证令牌时.

    相反,我决定复制Django如何做到这一点:

    将timestamp_today转换为base36 as today

    将user.id转换为base36 as ident

    创建hash包含:

    timestamp_today

    用户身份

    user.last_login

    用户密码

    user.email

    用隐藏的秘密来填充哈希

    创建一个路由,如:/ change-password/:ident/ :today-:hash

    我们测试req.params.timestamp,以便测试它是否适用于今天,最便宜的测试.先失败了.

    然后我们找到用户,如果它不存在则失败.

    然后我们从上面再次生成哈希,但是来自req.params的时间戳

    如果出现以下情况,重置链

    他们记得他们的密码和登录(last_login更改)

    他们实际上仍然登录并且:

    只需更改密码(密码更改)

    只需更改电子邮件(电子邮件更改)

    明天到了(时间戳变化太大)

    这条路:

    你没有在数据库中存储这些短暂的东西

    当令牌的目的是改变事物的状态,并且事物状态改变时,令牌的目的不再是安全相关的.

    2023-02-13 20:51 回答
  • 我尝试使用node-password-reset作为Matt617建议,但并不真正关心它.这是目前搜索中唯一出现的问题.

    所以一些时间挖掘,我发现自己更容易实现这一点.最后,我花了大约一天的时间来获取所有路线,用户界面,电子邮件和所有工作.我仍然需要增强安全性(重置计数器以防止滥用等),但是基本工作正常:

      创建了两个新路由,/ forgot和/ reset,这些路由不需要用户登录即可访问.

      GET on/forgot显示一个带有一个电子邮件输入的UI.

      POST /忘记检查是否有用户具有该地址并生成随机令牌.

      使用令牌和到期日更新用户的记录

      发送电子邮件至/ reset/{token}的链接

      GET on/reset/{token}检查是否存在具有该令牌但尚未过期的用户,然后显示具有新密码条目的UI.

      POST/reset(发送新的pwd和令牌)检查是否存在具有该令牌但尚未过期的用户.

      更新用户密码.

      将用户的令牌和到期日期设置为null

    这是我生成令牌的代码(取自node-password-reset):

    function generateToken() {
        var buf = new Buffer(16);
        for (var i = 0; i < buf.length; i++) {
            buf[i] = Math.floor(Math.random() * 256);
        }
        var id = buf.toString('base64');
        return id;
    }
    

    希望这可以帮助.

    编辑:这是app.js. 注意我将整个用户对象保留在会话中.我计划将来搬到沙发基地或类似的地方.

    var express = require('express');
    var path = require('path');
    var favicon = require('static-favicon');
    var flash = require('connect-flash');
    var morgan = require('morgan');
    var cookieParser = require('cookie-parser');
    var cookieSession = require('cookie-session');
    var bodyParser = require('body-parser');
    var http = require('http');
    var https = require('https');
    var fs = require('fs');
    var path = require('path');
    var passport = require('passport');
    var LocalStrategy = require('passport-local').Strategy;
    
    var app = express();
    app.set('port', 3000);
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'jade');
    
    var cookies = cookieSession({
        name: 'abc123',
        secret: 'mysecret',
        maxage: 10 * 60 * 1000
    });
    app.use(cookies);
    app.use(favicon());
    app.use(flash());
    app.use(morgan());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded());
    app.use(cookieParser());
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(express.static(path.join(__dirname, 'public')));
    
    module.exports = app;
    
    passport.use(new LocalStrategy(function (username, password, done) {
        return users.validateUser(username, password, done);
    }));
    
    //KEEP ENTIRE USER OBJECT IN THE SESSION
    passport.serializeUser(function (user, done) {
        done(null, user);
    });
    passport.deserializeUser(function (user, done) {
        done(null, user);
    });
    
    //Error handling after everything else
    app.use(logErrors); //log all errors
    app.use(clientErrorHandler); //special handler for xhr
    app.use(errorHandler); //basic handler
    
    http.createServer(app).listen(app.get('port'), function () {
        console.log('Express server listening on HTTP port ' + app.get('port'));
    });
    

    编辑:这是路线.

    app.get('/forgot', function (req, res) {
        if (req.isAuthenticated()) {
            //user is alreay logged in
            return res.redirect('/');
        }
    
        //UI with one input for email
        res.render('forgot');
    });
    
    app.post('/forgot', function (req, res) {
        if (req.isAuthenticated()) {
            //user is alreay logged in
            return res.redirect('/');
        }
        users.forgot(req, res, function (err) {
            if (err) {
                req.flash('error', err);
            }
            else {
                req.flash('success', 'Please check your email for further instructions.');
            }
            res.redirect('/');
        });
    });
    
    app.get('/reset/:token', function (req, res) {
        if (req.isAuthenticated()) {
            //user is alreay logged in
            return res.redirect('/');
        }
        var token = req.params.token;
        users.checkReset(token, req, res, function (err, data) {
            if (err)
                req.flash('error', err);
    
            //show the UI with new password entry
            res.render('reset');
        });
    });
    
    app.post('/reset', function (req, res) {
        if (req.isAuthenticated()) {
            //user is alreay logged in
            return res.redirect('/');
        }
        users.reset(req, res, function (err) {
            if (err) {
                req.flash('error', err);
                return res.redirect('/reset');
            }
            else {
                req.flash('success', 'Password successfully reset.  Please login using new password.');
                return res.redirect('/login');
            }
        });
    });
    

    2023-02-13 20:52 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有