PHPログインシステム:私(永続的なCookie)を覚えておいてください[重複

StackOverflow https://stackoverflow.com/questions/3128985

質問

この質問にはすでに答えがあります:

ログインする前に、「覚えておく」チェックボックスオプションを追加したいと思います。

ユーザーのブラウザにCookieを安全に保存する最良の方法は何ですか?

たとえば、Facebookには「Remember Me」チェックボックスがあり、Facebook.comを入力するたびにすでにログインしています。

私の現在のログインは、簡単なセッションを使用しています。

役に立ちましたか?

解決

この質問はたくさん尋ねられます、ここにあなたのためのいくつかのリンクがあります。

また、この質問に対する答えで一緒に集められたいくつかの素晴らしいリソースもあります。 ウェブサイト認証の決定的なガイド

他のヒント

更新(2017-08-13): :なぜ私たちが分離しているのかを理解するために selectortoken, 、aを使用するだけではありません token, 、 読んでください タイミング攻撃を防ぐためにトークンを分割することに関するこの記事 選択したクエリで。

このブログ投稿で概説した戦略を抽出します 安全な長期認証について それは多くの根拠をカバーしており、私たちは "私を覚えてますか" 部。

プリアンブル - データベース構造

このように見えるユーザーのテーブルから別のテーブルが必要です(mysql):

CREATE TABLE `auth_tokens` (
    `id` integer(11) not null UNSIGNED AUTO_INCREMENT,
    `selector` char(12),
    `token` char(64),
    `userid` integer(11) not null UNSIGNED,
    `expires` datetime,
    PRIMARY KEY (`id`)
);

ここで重要なことはそれです selectortoken 別々のフィールドです。

ログインした後

持っていない場合 random_bytes(), 、のコピーをつかむだけです random_compat.

if ($login->success && $login->rememberMe) { // However you implement it
    $selector = base64_encode(random_bytes(9));
    $authenticator = random_bytes(33);

    setcookie(
        'remember',
         $selector.':'.base64_encode($authenticator),
         time() + 864000,
         '/',
         'yourdomain.com',
         true, // TLS-only
         true  // http-only
    );

    $database->exec(
        "INSERT INTO auth_tokens (selector, token, userid, expires) VALUES (?, ?, ?, ?)", 
        [
            $selector,
            hash('sha256', $authenticator),
            $login->userId,
            date('Y-m-d\TH:i:s', time() + 864000)
        ]
    );
}

ページの読み込みで再認識します

if (empty($_SESSION['userid']) && !empty($_COOKIE['remember'])) {
    list($selector, $authenticator) = explode(':', $_COOKIE['remember']);

    $row = $database->selectRow(
        "SELECT * FROM auth_tokens WHERE selector = ?",
        [
            $selector
        ]
    );

    if (hash_equals($row['token'], hash('sha256', base64_decode($authenticator)))) {
        $_SESSION['userid'] = $row['userid'];
        // Then regenerate login token as above
    }
}

詳細

セレクターには、9バイトのランダムデータ(12文字にエンコードされたBase64)を使用します。これにより、72ビットのキースペースが提供されるため、2が2つあります36 衝突抵抗(誕生日攻撃)のビット、これはストレージ容量よりも大きい(integer(11) UNSIGNED)16倍。

実際の認証器には、33バイト(264ビット)のランダム性を使用します。これは、すべての実用的なシナリオで予測不可能である必要があります。

データベースにAuthenticatorのSHA256ハッシュを保存します。これにより、情報が漏れた後のユーザーのなりすましのリスクが軽減されます。

ユーザーのCookieに保存されている認証因子値のSHA256ハッシュを再計算し、保存されたSHA256ハッシュを使用して比較します hash_equals() タイミング攻撃を防ぐため。

DBルックアップは一定の時間ではないため、セレクターを認証器から分離しました。これにより、劇的なパフォーマンスヒットを引き起こすことなく、検索に対するタイミングリークの潜在的な影響がなくなります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top