2012-01-18 20 views
15

Ngắn

Làm việc trên hệ thống đăng nhập và cố gắng triển khai tính năng nhớ tôi. Gần đây, tôi đã nghiên cứu về chủ đề này, đọc rất nhiều bài báo, bài viết, truyện, tiểu thuyết, truyện cổ tích (gọi chúng như vậy, bởi vì một số trong số chúng không chứa 1 dòng mã, chỉ cần tải từ). về, lỗ hổng Cookie như cố định, chiếm quyền điều khiển ... vvCách thích hợp để sử dụng chức năng "Nhớ thông tin đăng nhập của tôi" trong PHP

và quyết định để đạt được các mục tiêu sau đây

  1. để thiết lập thời gian trễ giữa nỗ lực đăng nhập (để ngăn chặn các cuộc tấn công bruteforce) và để hạn chế những nỗ lực đếm
  2. Để tạo lại id phiên trên gần như mọi hoạt động

Nhưng Tôi thực sự bối rối về vấn đề chính của mình: cách nào là phù hợp, đối với tính năng "nhớ tôi"? sử dụng cookie/phiên/cơ sở dữ liệu?

Và xin giải thích ý tưởng của bạn vào mã. (Tôi không thể hiểu rõ ràng mà không cần code)

Chi tiết

Hiện nay, mã của tôi trông như thế

Trong khi đăng nhập Tôi đang sử dụng chức năng sau để thiết lập các tập tin cookie và session

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; 
} 

sau đó, trên các trang sử dụng an toàn, kiểm tra user_id sử dụng user_id để lấy tất cả các quan trọng dữ liệu về người dùng từ db

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

Chỉ cần một bình luận: Từ góc độ UX, tôi nghĩ đó là một điểm tốt để cho người dùng biết liệu bạn có nghĩa là "giữ tôi đăng nhập" hay chỉ "nhớ danh tính của tôi". – PapaFreud

+0

Bản sao có thể xảy ra: http://stackoverflow.com/questions/244882/what-is-the-best-way-to-implement-remember-me-for-a-website – ThinkingMonkey

+0

@ThinkingMonkey ok, you'r cool :) –

Trả lời

2

Nhưng tôi thực sự nhầm lẫn về vấn đề chính của mình: cách nào là phù hợp, đối với tính năng "nhớ tôi"? sử dụng cookie/phiên/cơ sở dữ liệu?

Http là một protocall không quốc tịch. Mã xác thực phải tồn tại để giữ trạng thái. Cách thích hợp là sử dụng phiên. Bây giờ bạn theo dõi phiên làm việc như thế nào? Tuỳ bạn. Nhưng cookie không phải là xấu.

Trong phiên, bạn có thể lưu băm được tạo từ trình duyệt các tiêu chí khác nhau (tác nhân người dùng, os, độ phân giải màn hình, v.v.) để kiểm tra xem mã thông báo có thuộc cùng một môi trường hay không. Bạn càng tiết kiệm được nhiều tiêu chí hơn thì sẽ càng khó khăn hơn. Btw bạn cần JavaScript để lấy thông tin bổ sung ths mỗi lần.

+2

Tôi ghét downvoting, nhưng 'thử gửi nó qua URL (tôi biết nó trông xấu xí) .' - thực sự là mục tiêu cho downvote. Nó nổi tiếng ** tấn công cố định cookie ** lỗ hổng –

3

Nếu bạn muốn một ví dụ về một "nhớ đến tôi" chức năng với mã, bạn có thể kiểm tra thư viện PHP của tôi tại https://github.com/gbirke/rememberme

+0

Tôi đã làm việc trên firefox. Nhưng trên chrome, tệp thử nghiệm của bạn không hoạt động: ở trên trang đầu tiên, không đăng nhập. –

+0

Tôi có thể dành 5-10 phút của bạn không? xin vui lòng thêm tôi tural.teyyuboglu trong skype –

8

Để thiết lập thời gian trễ giữa nỗ lực đăng nhập (để ngăn chặn các cuộc tấn công bruteforce) và để giới hạn số lần thử

Vì vậy, bạn đang cung cấp một phương pháp cho DOS theo tài khoản?

Để tái tạo id phiên trên gần như mọi hoạt động

erm, không có. Đó thực sự là khả năng đánh bại đối tượng. Bạn nên luôn tạo một id mới khi id hiện tại hết hạn hoặc khi người dùng được xác thực - nếu không, hãy để nó một mình.

Nhưng tôi thực sự nhầm lẫn về vấn đề chính của mình: cách nào là phù hợp, đối với tính năng "nhớ tôi"? sử dụng cookie/phiên/cơ sở dữ liệu?

Vì bạn cần giữ lại mã thông báo trên máy khách, điều đó có nghĩa là cookie (trừ khi bạn thích viết một cái gì đó thực sự phức tạp bằng cách sử dụng bộ nhớ cục bộ). Vì bạn không muốn để lộ dữ liệu thông qua cookie/làm cho giả mạo đơn giản có nghĩa là nó phải là một giá trị ngẫu nhiên.Và để đối chiếu giá trị ngẫu nhiên được lưu trữ, điều đó có nghĩa là lưu trữ dữ liệu serverside - có thể trong cơ sở dữ liệu vì nó phải có khả năng tham chiếu dữ liệu dựa trên id người dùng hoặc dựa trên giá trị ngẫu nhiên.

Mặc dù bạn chỉ có thể sử dụng phiên không hết hạn (hoặc đã sống lâu), tôi sẽ tránh xa điều này - dữ liệu sẽ trượt tuyết - và bạn nên gia hạn dữ liệu phiên một lần trong một thời gian.

Bạn cũng cần phải phục vụ cho trường hợp người dùng muốn bạn nhớ cô ấy trên 2 máy tính khác nhau. Nếu bạn chỉ giữ một mã thông báo 'nhớ tôi' cho mỗi tài khoản, thì bạn sẽ phải sử dụng cùng một giá trị ở cả hai khách hàng hoặc xóa mã thông báo cũ khi tạo một mã mới (nghĩa là người dùng chỉ có thể được ghi nhớ trên một máy).

hãy giải thích ý tưởng của bạn về mã. Tôi không thể hiểu rõ ràng nếu không có mã số

No. Tôi được trả tiền để viết mã; Nếu bạn muốn tôi viết mã cho bạn thì bạn sẽ phải trả tiền cho tôi. Và mã sẽ chiếm nhiều không gian và thời gian hơn so với mô tả ở trên.

+3

1 cho lời giải thích lý do tại sao bạn không viết mã. –

+0

Trong cộng đồng này, chúng tôi đang cố gắng giúp đỡ lẫn nhau. Tôi cũng là nhà phát triển. Chỉ muốn nhận được lời khuyên và một số ví dụ về ý tưởng của bạn, (Tôi không phải là người nói tiếng Anh. Không phải tất cả bài đăng của bạn 100% rõ ràng với tôi) Dù sao, cảm ơn bạn đã lãng phí thời gian của bạn miễn phí :) –

Các vấn đề liên quan