Asp.net 重置密码页面上的用户验证

Asp.net 重置密码页面上的用户验证,asp.net,forgot-password,Asp.net,Forgot Password,我正在为我的网站写一个密码重置页面。以下是我的想法: a。用户单击登录页面上的“忘记密码”链接 b。重定向到我的密码重置页面 c。用户输入他的电子邮件地址 d。发送到电子邮件地址的电子邮件,带有重置其密码的链接。链接中有类似于?code=“xxxx”的安全代码 e。用户打开链接并输入新密码,然后单击提交按钮 f。我的页面更改用户的密码 我的问题是关于步骤f。在步骤e中,当用户打开链接时,我可以验证他的安全代码,然后向用户显示“新密码”和“确认密码”字段。但是当用户点击提交按钮时,我怎么知道这是用

我正在为我的网站写一个密码重置页面。以下是我的想法:

a。用户单击登录页面上的“忘记密码”链接

b。重定向到我的密码重置页面

c。用户输入他的电子邮件地址

d。发送到电子邮件地址的电子邮件,带有重置其密码的链接。链接中有类似于?code=“xxxx”的安全代码

e。用户打开链接并输入新密码,然后单击提交按钮

f。我的页面更改用户的密码

我的问题是关于步骤f。在步骤e中,当用户打开链接时,我可以验证他的安全代码,然后向用户显示“新密码”和“确认密码”字段。但是当用户点击提交按钮时,我怎么知道这是用户而不是黑客提交的真实请求呢?也许我错了,但我认为黑客可以很容易地模拟这样的字段数据,因为并没有验证字段

我可以想出一些方法来验证步骤f中的请求,但我不知道它们是否正确。 1.在步骤e中添加加密的cookie,并在步骤f中检查它? 2.在步骤e中使用会话变量,并在步骤f中检查它? 3.在步骤e中添加隐藏字段,并在步骤f中进行检查

这些方法行吗?哪一个更好,或者有更好的吗


提前感谢。

如果您通过电子邮件发送的代码是GUID或类似ID,则从统计上看,很少有人能猜到该代码。如果您另外有一个链接,包括他们电子邮件的散列版本或其他一些将代码链接到用户的方式,我认为您将非常安全,不会受到恶意输入的影响


我更担心的是,人们会从c/d步骤中收到垃圾邮件,除非你正在对数据库中当前存在的电子邮件进行某种验证。

输入用户名和重置代码的用户应该像用户名和密码一样将他们登录到网站。不同之处在于,您可以立即强制他们更改密码。使用此密码重置方法,您可以隐式地相信用户是发送代码的电子邮件帐户的所有者

编辑: 好的,我对ASP.net一无所知

然而,我以前处理过很多次这个问题。以下是我的PHP解决方案:

<?php
class AuthController extends Zend_Controller_Action
{
    public function identifyAction()
    {
        if ($this->_request->isPost()) {
            $username = $this->_getParam('username');
            $password = $this->_getParam('password');

            if (empty($username) || empty($password)) {
                $this->_flashError('Username or password cannot be blank.');
            } else {
                $user = new User();
                $result = $user->login($username, $password);

                if ($result->isValid()) {
                    $user->fromArray((array) $this->_auth->getIdentity());

                    if ($this->_getParam('changepass') || $user->is_password_expired) {
                        $this->_redirect('auth/change-password');
                        return;
                    }
                    $this->_doRedirect($user);
                    return;
                } else {
                    $this->_doFailure($result->getIdentity());
                }
            }
        }
        $this->_redirect('/');
    }

    public function forgotPasswordAction()
    {
        if ($this->_request->isPost()) {
            // Pseudo-random uppercase 6 digit hex value
            $resetCode = strtoupper(substr(sha1(uniqid(rand(),true)),0,6));

            Doctrine_Query::create()
                ->update('dUser u')
                ->set('u.reset_code', '?', array($resetCode))
                ->where('u.username = ?', array($this->_getParam('username')))
                ->execute();

            $mail = new Zend_Mail();
            $mail->setBodyText($this->_resetEmailBody($this->_getParam('username'), $resetCode));
            $mail->setFrom('no-reply@example.com', 'Example');
            $mail->addTo($this->_getParam('username'));
            $mail->setSubject('Forgotten Password Request');
            $mail->send();


            $this->_flashNotice("Password reset request received.");
            $this->_flashNotice("An email with further instructions, including your <em>Reset Code</em>, has been sent to {$this->_getParam('username')}.");
            $this->_redirect("auth/reset-password/username/{$this->_getParam('username')}");
        }
    }

    public function resetPasswordAction()
    {
        $this->view->username = $this->_getParam('username');
        $this->view->reset_code = $this->_getParam('reset_code');

        if ($this->_request->isPost()) {
            $formData = $this->_request->getParams();
            if (empty($formData['username']) || empty($formData['reset_code'])) {
                $this->_flashError('Username or reset code cannot be blank.');
                $this->_redirect('auth/reset-password');
            } elseif ($formData['new_password'] !== $formData['confirm_password']) {
                $this->_flashError('Password and confirmation do not match.');
                $this->_redirect('auth/reset-password');
            } else {
                $user = new User();
                $result = $user->loginWithResetCode($formData['username'], $formData['reset_code']);

                if ($result->isValid()) {
                    $user->updatePassword($result->getIdentity(), $formData['new_password']);

                    $user->fromArray((array) $this->_auth->getIdentity());
                    $this->_setLegacySessionData($user);

                    $this->_flashNotice('Password updated successfully!');
                    $this->_doRedirect($user);
                } else {
                    $this->_doFailure($result->getIdentity());
                    $this->_redirect('auth/reset-password');
                }
            }
        }
    }

    protected function _doFailure($username)
    {
        $user = Query::create()
            ->from('User u')
            ->select('u.is_locked')
            ->where('u.username = ?', array($username))
            ->fetchOne();

        if ($user->is_locked) {
            $lockedMessage = Config::get('auth.lock_message');
            if (!$lockedMessage) {
                $lockedMessage = 'This account has been locked.';
            }
            $this->_flashError($lockedMessage);
        } else {
            $this->_flashError('Invalid username or password');
        }
    }
}

但我检查了服务器站点,发现它们在恢复用户密码时不会让用户登录。这两个密码字段仅用于重置密码,而不是更改密码。我看不出您的评论与我的答案有什么关联。我的意思是,在服务器网站上,用户输入用户名和重置代码时不会登录。它只是将用户引导到一个页面以更改其密码,但他们没有登录。hobodave,感谢您的代码和摘要。他们帮了大忙。但我认为这些代码在恢复用户密码时仍然会记录用户的日志。为什么不呢,我会试着接近。谢谢