3

Web サイトのパスワード リセット ページを作成しています。ここに私の考えがあります:

を。ユーザーは、ログイン ページで「パスワードを忘れた」リンクをクリックします。

b. パスワードリセットページにリダイレクト

c. ユーザーは自分のメールアドレスを入力してください

d. パスワードをリセットするためのリンクが記載された電子メール メッセージが電子メール アドレスに送信されます。リンクには ?code="xxxx" のようなセキュリティ コードが含まれています。

e. ユーザーはリンクを開いて新しいパスワードを入力し、送信ボタンをクリックします。

f. マイページでユーザーのパスワードを変更します。

私の質問はステップfです。ステップ e で、ユーザーがリンクを開いたときに、セキュリティ コードを確認し、「新しいパスワード」フィールドと「パスワードの確認」フィールドをユーザーに表示することができました。しかし、ユーザーが送信ボタンをクリックしたとき、これがハッカーではなくユーザーによって送信された実際の要求であることをどのように知ることができますか? 間違っているかもしれませんが、検証フィールドがないため、ハッカーはそのようなフィールド データを簡単にシミュレートできると思います。

ステップ f で要求を検証するために考えられるアイデアがいくつかありますが、それらが正しいかどうかはわかりません。1. 手順 e で暗号化された Cookie を追加し、手順 f で確認しますか? 2. 手順 e でセッション変数を使用し、手順 f で確認しますか? 3. 手順 e で隠しフィールドを追加し、手順 f で確認しますか?

それらのアプローチは大丈夫ですか?どちらが優れているか、または他に優れているものはありますか?

前もって感謝します。

4

2 に答える 2

3

ユーザー名とリセット コードを入力するユーザーは、ユーザー名とパスワードと同じようにサイトにログインする必要があります。違いは、すぐにパスワードの変更を強制することです。このパスワード リセット方法では、コードが送信された電子メール アカウントの所有者がユーザーであることを暗黙のうちに信頼しています。

編集:

わかりました、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');
        }
    }
}

これに従うことができれば、何をすべきかについての良いアイデアが得られるはずです。私は要約しようとします:

識別アクション

これは、ユーザー名とパスワードを使用した通常の「ログイン」です。ユーザーをログインさせ、ID をセッションに保存します。

パスワードを忘れたアクション

これにより、ユーザー名を要求するフォームがユーザーに表示されます。ユーザー名を入力すると、リセット コードが生成され、ユーザー テーブルのエントリに格納され、電子メールで送信され、パスワードのリセット ページにリダイレクトされます。このページは認証されていません。ユーザーはログインしていません。

resetPasswordAction

これは、ユーザーに「resetPassword」フォームが表示される場所です。ユーザー名と、電子メールで受け取ったリセット コードを提供する必要があります。これは、リセット コードがパスワードであるかのように、指定されたユーザー名とリセット コードでユーザーを認証します。クレデンシャルが有効な場合、ユーザーは changePassword アクションにリダイレクトされ、そこでパスワードの変更が許可されます。changePasswordAction (表示されていません)では、ユーザー名/パスワードまたはユーザー名/resetCode を使用してユーザーを認証 (ログイン) する必要があります。

お役に立てれば。

于 2010-01-09T07:48:35.027 に答える
0

電子メールで送信するコードが GUID またはそのような ID である場合、誰かがそのコードを推測できる可能性は統計的に低いです。さらに、リンクにメールのハッシュ化されたバージョンまたはコードをユーザーにリンクする他の方法が含まれていれば、悪意のある入力からかなり安全になると思います.

データベースに現在存在する電子メールの何らかの検証を行っていない限り、ステップ c/d から人々がスパムされているのではないかと心配しています。

于 2010-01-09T07:45:12.600 に答える