2012-01-18 1 views
15

짧은

로그인 시스템에서 작동하고 Remember Me 기능을 구현하려고합니다.PHP의 "Remember me"기능을 올바르게 사용하는 방법

최근에 나는 기사, 게시물, 이야기, 소설, 동화 등을 읽으며 (이 중 일부는 1 줄의 코드도 포함되어 있지 않으므로 너무 많이 부르기 때문에)이 주제에 대한 연구를 수행했습니다. 등 고정, 납치 ... 같은 쿠키 취약점에 대한

은 그리고 (bruteforce 공격을 방지하기 위해) 및 시도 을 계산 제한 로그인 시도 사이의 시간 지연을 설정하려면 다음과 같은 목표

  1. 을 달성하기로 결정
  2. 거의 모든 작업에서 세션 ID를 다시 생성하려면

그러나 나는 내 주요 문제에 대해 정말로 혼란 스럽다. "기억하는"기능을 위해 어떤 방법이 적절합니까? 쿠키/세션/데이터베이스를 사용 하시겠습니까?

그리고 코드에 대한 당신의 생각을 설명해주십시오.

은 자세한

는 현재, 내 코드는 동안 그

처럼 보이는 (내가 코드없이 명확하게 이해할 수) 로그인에 내가 사용하고 있습니다 기능을 다음과 같은 모든 중요한을 가져 user_id를 사용하여 user_id 확인, 보안 사용자 페이지에

protected function validateUser($userid, $ckey=0, $rememmber=0) { 
    session_start(); 
    session_regenerate_id(true); //this is a security measure 
    $_SESSION['user_id'] = $userid; 
    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']); 
    if (isset($remember) && $rememmber == 'on') { 
     setcookie("user_id", $_SESSION['user_id'], time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/"); 
     setcookie("user_key", sha1($ckey), time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/"); 
    } 
    return true; 
} 

그리고 쿠키와 세션을 설정합니다 당신이 코드는 "나를 기억"기능의 예를 원하는 경우

public function protect() { 
     session_start(); 

     /* Secure against Session Hijacking by checking user agent */ 
     if (isset($_SESSION['HTTP_USER_AGENT'])) { 
      if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) { 
       $this->signout(); 
       exit; 
      } 
     } 

// before we allow sessions, we need to check authentication key - ckey and ctime stored in database 

     /* If session not set, check for cookies set by Remember me */ 
     if (!isset($_SESSION['user_id'])) { 
      if (isset($_COOKIE['user_id']) && isset($_COOKIE['user_key'])) { 
       /* we double check cookie expiry time against stored in database */ 

       $cookie_user_id = $_COOKIE['user_id']; 
           $stmt = $this->db->prepare("select `ckey`,`ctime` from `users` where `id` =?") or die($this->db->error); 
      $stmt->bind_param("i", $cookie_user_id) or die(htmlspecialchars($stmt->error)); 
      $stmt->execute() or die(htmlspecialchars($stmt->error)); 
      $stmt->bind_result($ckey, $ctime) or die($stmt->error); 
      $stmt->close() or die(htmlspecialchars($stmt->error)); 
       // coookie expiry 
       if ((time() - $ctime) > 60 * 60 * 24 * COOKIE_TIME_OUT) { 
        $this->signout(); 
       } 
       /* Security check with untrusted cookies - dont trust value stored in cookie.  
        /* We also do authentication check of the `ckey` stored in cookie matches that stored in database during login */ 

       if (!empty($ckey) && is_numeric($_COOKIE['user_id']) && $_COOKIE['key'] == sha1($ckey)) { 
        session_regenerate_id(); //against session fixation attacks. 

        $_SESSION['user_id'] = $_COOKIE['user_id']; 
        $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']); 
       } else { 
        $this->signout(); 
       } 
      } else { 
       if ($page != 'main') { 
        header('Location:' . wsurl); 
        exit(); 
       } 
      } 
     } 
+1

단지 의견 : UX 관점에서 "로그인 상태 유지"또는 "내 신원 기억"이라는 의미인지 사용자에게 알려주는 것이 좋은 지적이라고 생각합니다. – PapaFreud

+0

가능성이있는 복제본 : http://stackoverflow.com/questions/244882/what-is-the-best-way-to-implement-remember-me-for-a-website – ThinkingMonkey

+0

@ThinkingMonkey 좋습니다. :) –

답변

2

하지만 내 주요 문제에 대해 정말 혼란 스러웠습니다. 어떤 방식 으로든 '기억 해요'기능이 적합합니까? 쿠키/세션/데이터베이스를 사용 하시겠습니까?

Http는 stateless protocall입니다. 인증 토큰은 상태를 유지하기 위해 유지되어야합니다. 올바른 방법은 세션을 사용하는 것입니다. 이제 세션을 어떻게 추적합니까? 그것은 당신에게 달려 있습니다. 그러나 쿠키는 나쁘지 않습니다.

세션에서 다른 환경 (사용자 에이전트, OS, 화면 해상도 등)에서 생성 된 해시를 저장하여 토큰이 동일한 환경에 있는지 확인할 수 있습니다. 당신이 더 많은 기준을 정할수록 탈취가 더 어려워집니다. 매번 추가 정보를 얻으려면 JavaScript가 필요합니다.

+2

나는 downvoting을 싫어하지만 'URL을 통해 전송 해보십시오. (추한 것처럼 보입니다.) - 실제로 downvote의 대상입니다. 잘 알려진 ** 쿠키 고정 공격 ** 취약점 –

3

DB를에서 사용자에 대한 데이터가 있습니다 (로그인 시도 사이의 시간 지연을 설정하려면 https://github.com/gbirke/rememberme

+0

나는 파이어 폭스에서 작동하도록했습니다. 하지만 크롬에서 테스트 파일이 작동하지 않습니다. 첫 페이지에 머물러 있으면 로그인하지 않습니다. –

+0

5-10 분 정도 걸릴 수 있습니까? 나를 추가하시기 바랍니다 tural.teyyuboglu skype –

8

에서 내 PHP 라이브러리를 확인하실 수 있습니다 bruteforce 공격을 막기 위해) 시도 횟수를 제한하려면

그래서 도스 계정에 대한 방법을 제공하고 있습니까?

아니, 거의 모든 작업

음에 세션 ID를 다시 생성합니다. 실제로 그 대상을 물리 칠 수 있습니다. 현재 ID가 만료되거나 사용자가 인증 될 때 항상 새 ID를 생성해야합니다. 그렇지 않으면 그대로 두십시오.

하지만 내 주요 문제에 대해 정말 혼란 스러웠습니다. 어떤 방식 으로든 '기억하십시오'기능을 사용할 수 있습니까? 쿠키/세션/데이터베이스를 사용 하시겠습니까?

토큰을 클라이언트에 보관해야하므로 이는 쿠키를 의미합니다 (로컬 저장소를 사용하여 매우 복잡한 것을 작성하는 것이 좋습니다). 쿠키를 통해 데이터를 노출하고 싶지 않으므로 간단히 위조 할 수 있습니다. 이는 임의의 값이어야 함을 의미합니다.저장된 임의의 값을 조정하기 위해서는 데이터 서버를 저장하는 것이 좋습니다. 사용자 ID 또는 임의 값을 기반으로 데이터를 참조 할 수 있어야하므로 데이터베이스에 저장하는 것이 좋습니다.

만료되지 않는 (또는 수명이 긴) 세션을 사용할 수도 있지만 데이터가 눈덩이처럼 날아갈 것입니다. 세션 데이터를 한 번만 갱신하는 것이 좋습니다.

또한 사용자가 2 대의 다른 컴퓨터에서 그녀를 기억하기를 원할 경우를 대비해야합니다. 각 계정에 대해 하나의 'remember me'토큰 만 보유하면 새 클라이언트를 만들 때 두 클라이언트에서 동일한 값을 사용하거나 이전 토큰을 삭제해야합니다 (즉, 한 컴퓨터에서만 사용자를 기억할 수 있음).).

코드에 대한 아이디어를 설명해주세요. 코드 없이는 명확하게 이해할 수 없습니다.

아니요. 내가 당신에게 코드를 쓰게하고 싶다면 나에게 돈을 지불해야 할 것이다. 그리고 코드는 위의 설명보다 훨씬 많은 공간과 시간을 차지합니다.

+3

+1 이유에 대한 설명을 작성 코드. –

+0

이 커뮤니티에서는 서로 도우 려합니다. 나도 개발자 야. 그냥 조언과 조언의 코드 예제를 얻고 싶었습니다. (저는 영어로 말하는 사람이 아닙니다. 모든 게시물이 100 % 명확하지는 않습니다.) 어쨌든 무료로 시간을 낭비 해 주셔서 감사합니다. –