복붙노트

PHP 로그인 시스템 : Remember Me (영구 쿠키) [duplicate]

PHP

PHP 로그인 시스템 : Remember Me (영구 쿠키) [duplicate]

로그인하기 전에 "내 정보 기억"확인란을 추가하고 싶습니다.

사용자의 브라우저에 쿠키를 안전하게 저장하는 가장 좋은 방법은 무엇입니까?

예를 들어, Facebook은 "remember me"체크 박스를 가지고 있으므로 facebook.com을 입력 할 때마다 이미 로그인되어 있습니다.

현재 로그인은 간단한 세션을 사용합니다.

해결법

  1. ==============================

    1.이 질문은 많이 묻습니다. 여기에 몇 가지 링크가 있습니다.

    이 질문은 많이 묻습니다. 여기에 몇 가지 링크가 있습니다.

    또한이 질문에 대한 답변으로 수집 된 훌륭한 자료가 있습니다. 웹 사이트 인증에 대한 확실한 안내서

  2. ==============================

    2.나는 장기간의 안전한 인증에 관한이 블로그 게시물에 설명 된 전략을 추출 할 것인데, 그 이유는 이것이 많은 부분을 다루고 있으며, 우리는 "나를 기억한다"부분에만 관심이 있기 때문입니다.

    나는 장기간의 안전한 인증에 관한이 블로그 게시물에 설명 된 전략을 추출 할 것인데, 그 이유는 이것이 많은 부분을 다루고 있으며, 우리는 "나를 기억한다"부분에만 관심이 있기 때문입니다.

    우리는 사용자 테이블에서 다음과 같은 별도의 테이블을 원합니다 (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`)
    );
    

    여기서 중요한 것은 선택기와 토큰이 별도의 필드라는 것입니다.

    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 바이트의 임의 데이터 (base64를 12 문자로 인코딩)를 사용합니다. 이는 72 비트의 키 공간을 제공하므로 236 비트의 충돌 저항 (생일 공격)을 제공합니다. 이는 저장 용량 (정수 (11) UNSIGNED)보다 16 배 더 큽니다.

    우리는 실제 인증자를 위해 33 바이트 (264 비트)의 임의성을 사용합니다. 이것은 모든 실제 시나리오에서 예측할 수 없어야합니다.

    인증 자의 SHA256 해시를 데이터베이스에 저장합니다. 이렇게하면 정보 누출로 인한 사용자 위장의 위험이 완화됩니다.

    사용자의 쿠키에 저장된 authenticator 값의 SHA256 해시를 다시 계산 한 다음 hash_equals ()를 사용하여 저장된 SHA256 해시와 비교하여 타이밍 공격을 방지합니다.

    DB 조회가 일정 시간이 아니기 때문에 인증 프로그램에서 선택기를 분리했습니다. 이렇게하면 과감한 성능 저하없이 검색시 타이밍 누출의 잠재적 영향을 제거 할 수 있습니다.

  3. from https://stackoverflow.com/questions/3128985/php-login-system-remember-me-persistent-cookie by cc-by-sa and MIT license