Javascript 通过双击防止创建两次帐户

Javascript 通过双击防止创建两次帐户,javascript,node.js,express,passport.js,Javascript,Node.js,Express,Passport.js,我有一个应用程序,使用平均堆栈,最近我看到了一些奇怪的行为。现在这种情况并不是每次用户注册都会发生,到目前为止已经发生了3次。当用户注册时,应用程序将为该用户创建两个具有所有相同详细信息的帐户。现在,我已经添加了一些功能,可以检测用户是否已经存在该电子邮件,并将其重定向到登录页面,但似乎无法阻止该问题 这是我的密码: // ========================================================================= // LOCAL SIGN

我有一个应用程序,使用平均堆栈,最近我看到了一些奇怪的行为。现在这种情况并不是每次用户注册都会发生,到目前为止已经发生了3次。当用户注册时,应用程序将为该用户创建两个具有所有相同详细信息的帐户。现在,我已经添加了一些功能,可以检测用户是否已经存在该电子邮件,并将其重定向到登录页面,但似乎无法阻止该问题

这是我的密码:

// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'

passport.use('local-signup', new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        firstNameField: 'firstName',
        lastNameField: 'lastName',
        usernameField: 'email',
        passwordField: 'password',
        jobTitleField: 'jobTitle',
        startDateField: 'startDate',
        passReqToCallback: true // allows us to pass back the entire request to the callback
    },

    function(req, email, password, done) {

        // find a user whose email is the same as the forms email
        // we are checking to see if the user trying to login already exists
        User.findOne({'email': email}, function(err, user) {
            // if there are any errors, return the error
            if (err)
                return done(err);

            // check to see if theres already a user with that email
            if (user) {
                return done(null, false, {
                    message: 'That email is already taken.'
                });
            }
            else { var token = crypto.randomBytes().toString();
                  // if there is no user with that email
                  // create the user
                  var newUser = new User();

                 // set the user's local credentials
                newUser.firstName = req.body.firstName;
                newUser.lastName = req.body.lastName;
                newUser.email = email;
                newUser.password = newUser.generateHash(password); // use the generateHash function in our user model
                newUser.jobTitle = req.body.jobTitle;
                newUser.startDate = req.body.startDate;
                newUser.birthday = req.body.birthday;
                newUser.region = req.body.region;
                newUser.sector = req.body.sector;
                newUser.accountConfirmationToken = token;
                newUser.accountConfirmationTokenExpires = Date.now() + 3600000;
                newUser.accountVerified = 'false';
                newUser.isLineManager = 'false';

                // save the user
                newUser.save(function(err) {
                    if (err)
                        throw err;
                    else {

                        var data = {
                            from: 'system',
                            to: email,
                            subject: 'Account Verification',
                            text: 'You recently registered onto the App, to gain access to your account please verify your account.\n\n' +
                                'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
                                'http://' + req.headers.host + '/verify/' + token + '\n\n'
                        };

                        mailgun.messages().send(data, function(error, body) {
                            console.log(body);
                            console.log("setting token 1");
                            req.flash('info', 'An e-mail has been sent to ' + email + ' with further instructions.');
                        });
                        return done(null, newUser);
                    }
                });
            }

        });

    }));
我的结论:

我通过创建一个测试帐户来测试应用程序,一旦我填写了注册表,我就快速地在“立即注册”按钮上单击两次,当我检查数据库时,它创建了两个具有相同详细信息的帐户。基本上,它会发送两个POST请求来创建帐户,并且这两个请求都会得到批准。当只有1个应被批准时

我的问题:

  • 如果用户在注册时单击两次,如何解决此问题 按钮,它只创建一个帐户

  • 还有可能发生这种情况的另一个原因,是吗 上面的代码有问题吗

  • 谢谢

    编辑:

    应用程序配置代码:

    // configuration ===============================================================
    
    
    mongoose.connect(database.url);                                 // connect to mongoDB database on modulus.io
    require('./config/passport')(passport);
    app.use(express.static(__dirname + '/public'));  
    app.use(express.static(__dirname + '/views'));  // set the static files location /public/img will be /img for users
    app.use(busboy());
    app.use(compression()); //use compression
    app.use(morgan('dev'));                                         // log every request to the console
    app.use(bodyParser.urlencoded({'extended': true}));             // parse application/x-www-form-urlencoded
    app.use(bodyParser.json());                                     // parse application/json
    app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
    app.use(methodOverride());
    app.use(cookieParser());                                        // read cookies (needed for auth)
    app.set('view engine', 'ejs');                                  // set up ejs for templating
    
    // required for passport
    app.use(session({ secret: ''})); // session secret
    app.use(passport.initialize());
    app.use(passport.session());                                    // persistent login sessions
    app.use(flash());                                               // use connect-flash for flash messages stored in session
    
    编辑:

    路线代码:

    app.post('/signup', function(req, res, next) {
    passport.authenticate('local-signup', function(err, user, info) {
        if (err) {
            return next(err);
        }
        if (!user) {
            return res.json({
                message: 'An account with this email is already registered. Please try to login, if you cant remeber the password then please use our password reset service'
            })
        }
        req.logIn(user, function(err) {
            if (err) {
                return next(err);
            }
            return res.json({
                redirectUrl: '/verifyAccount',
                message: 'We have sent an email to verify your email. Once you have verified your account you will be able to login'
            });
        });
    })(req, res, next);
    });
    

    您可以在第一次按下时禁用注册按钮,以防止双击它

    您可以在第一次按下时禁用注册按钮,以防止双击它

  • 作为一种解决方案,我可以建议您在
    电子邮件
    列上设置
    唯一约束
    ,这将不允许在现有电子邮件中插入行

  • 那么使用LocalStrategy的代码呢,它应该可以正常工作,但是您可以只覆盖
    usernameField
    passwordField
    (因此,您可以删除其他字段)。使用
    req.body
    获取其他表单数据,就像您已经做的那样(以防重构)

  • 作为一种解决方案,我可以建议您在
    电子邮件
    列上设置
    唯一约束
    ,这将不允许在现有电子邮件中插入行

  • 那么使用LocalStrategy的代码呢,它应该可以正常工作,但是您可以只覆盖
    usernameField
    passwordField
    (因此,您可以删除其他字段)。使用
    req.body
    获取其他表单数据,就像您已经做的那样(以防重构)


  • 问题必须是由于node.js中的db异步操作造成的。检查您的流程,使用callback。您是否也可以发布您的
    中间件
    代码?(您的
    app.configure
    block所在的位置)@DavidR您是指我的
    server.js
    文件中配置整个应用程序的代码?或者调用
    本地注册
    功能的中间件路由?我指的是
    服务器.js
    ,您在那里拥有所有应用程序配置。@DavidR请查看更新的问题,问题一定是由于与node.js中的db进行异步操作造成的。检查您的流程,使用callback。您是否也可以发布您的
    中间件
    代码?(您的
    app.configure
    block所在的位置)@DavidR您是指我的
    server.js
    文件中配置整个应用程序的代码?或者调用
    本地注册
    功能的中间件路由?我指的是
    服务器.js
    ,您在那里拥有所有应用程序配置。@DavidR请查看更新的问题是,但这并不能解决代码中的主要问题。我知道,那只是一种工作。我不知道nodejs,但我想到的唯一一件事是,当你的应用程序开始处理第一个请求或使用事务时,尝试锁定数据库写入是的,但这并不能解决代码中的主要问题。我知道,那只是一种工作。我不知道nodejs,但我想到的唯一一件事是,当应用程序开始处理第一个请求或使用事务时,尝试锁定数据库写入