2011-10-21 28 views
5

Thành thật mà nói, nó gây ra quá nhiều rắc rối trong v1.0 để có chức năng yêu cầu ba lần gửi biểu mẫu, với $_SESSION dữ liệu phiên giữ tất cả nội dung trung gian - chỉ để người dùng bắt đầu một hoạt động, sau đó mở tab thứ hai và thực hiện một hoạt động thứ hai mà chà đạp qua dữ liệu phiên.Làm cách nào để hạn chế ứng dụng của tôi thành một tab trình duyệt?

Tôi nghi ngờ rằng điều này là độc hại (nhưng không thể giảm giá). Nhiều khả năng người dùng bắt đầu một hoạt động, bị gián đoạn, quên rằng họ đã bắt đầu hoặc không thể tìm thấy tab gốc để bắt đầu lại (sau đó tìm tab gốc và cố gắng hoàn thành thao tác lần thứ hai).

Vì tôi đang viết mã bằng PHP, tôi có thể phát hiện sự tồn tại của dữ liệu phiên trong quá trình gửi biểu mẫu (làm cách nào để làm điều đó với JS nếu người dùng mở nhiều tab khác - tôi đoán rằng tôi sẽ cần Ajax - phải không?) .

Vì vậy, mỗi khi tôi bắt đầu một hoạt động, tôi kiểm tra cờ trong dữ liệu phiên và nếu tôi đặt lại thành “Tôi rất tiếc, Dave. Tôi sợ tôi không thể làm điều đó ”trang, khác tôi đặt cờ và tiếp tục (nhớ để xóa nó vào cuối của hoạt động).

Tôi đoán điều đó sẽ hiệu quả, nhưng:
1) Có thể chấp nhận giới hạn các ứng dụng trình duyệt cho một tab/cá thể không?
2) Tôi có nên cố gắng cho phép nhiều phiên bản trong v2.0 không?

Bất kỳ nhận xét, trợ giúp hoặc lời khuyên nào khác?

+0

Nếu gặp sự cố này, có thể bạn cũng gặp sự cố với người dùng nhấp vào nút Quay lại của trình duyệt và sau đó tương tác với trang trước, ngay cả khi không có nhiều tab. Bạn không thể giả định rằng '$ _SESSION' luôn đồng bộ với trình duyệt. – Wyzard

Trả lời

5

Thiết kế tốt hơn là tránh lưu trữ trạng thái tương tác của người dùng trong phiên. Đặt nó trong các trường biểu mẫu ẩn hoặc một thứ gì đó sao cho mỗi yêu cầu của khách hàng mang trạng thái kết hợp của nó với nó. Nếu bạn lo lắng về việc người dùng giả mạo nó, hãy sử dụng một HMAC để ngăn chặn điều đó và có thể mã hóa nó nếu nó chứa những thứ mà người dùng không thể xem được.

Chỉ nêu rõ rằng nên được chia sẻ giữa các tab - như danh tính đăng nhập của người dùng hoặc thứ gì đó giống như giỏ hàng - phải được lưu trữ trong phiên.

2

Với mọi trình duyệt hỗ trợ duyệt theo tab, sẽ là trải nghiệm người dùng kém để cố giới hạn duyệt web sang một tab (bạn cũng có thể tạo ứng dụng dành cho máy tính để bàn).

Một cách bạn có thể giải quyết vấn đề này là thêm mã thông báo CSRF vào biểu mẫu của bạn (dưới dạng biến ẩn), sẽ được gửi cùng với yêu cầu.

CSRF reference

Có rất nhiều cách để tạo ra được dấu hiệu, nhưng về cơ bản bạn:

  1. tạo token
  2. cửa hàng ở đầu ra $_SESSION
  3. của bạn vào mẫu với <input type="hidden" name="{token name}" value="{token value}" />

Sau đó, khi biểu mẫu gửi cho bạn c heck $_REQUEST['{token name}'] == $_SESSION[ {tên mã thông báo}] `.

Nếu mã thông báo đó khác nhau, bạn biết đó không phải là biểu mẫu bạn đã tạo ban đầu và do đó có thể bỏ qua yêu cầu cho đến khi biểu mẫu thực có mã thông báo chính xác.

Một điều: nếu kẻ tấn công có thể tìm ra cách bạn tạo mã thông báo CSRF của bạn thì họ có thể giả mạo yêu cầu.

+0

Có vẻ như tôi đã nói sai câu hỏi. Trình duyệt có thể mở bao nhiêu tab tùy thích - nhưng chỉ một tab có thể là của tôi – Mawg

4

Tối đa bạn có thể giữ danh sách "trang được yêu cầu cuối cùng" trong tệp phiên, với cờ để cho biết người dùng không được phép di chuyển nó nếu đó là một trong các cờ biểu mẫu quan trọng này. Vì vậy, nếu bạn đang ở trên form.php và đó là một no-move-off, thì bất kỳ trang mới nào được tải sẽ hiển thị tùy chọn "hủy hoặc đóng cửa sổ".

Bạn không thể ngăn người dùng mở một tab/cửa sổ khác, nhưng bạn có thể ngăn họ di chuyển đến nơi khác trong trang web của bạn trong các cửa sổ/tab khác đó.

Tuy nhiên, hãy xem xét đây là trải nghiệm người dùng rất kém. Hãy tưởng tượng nếu Amazon bị mắc kẹt trong trang giỏ hàng và không bao giờ cho phép bạn đến một trang khác mà không phải thực sự mua thứ gì đó. Xem xét cập nhật mã của bạn để cho phép nhiều cửa sổ khác nhau sử dụng cùng một biểu mẫu.

+0

+1 Tôi thích giải pháp của bạn. Và tôi đồng ý rằng nó phải được sửa trong 2.0, nhưng ... – Mawg

+0

btw, làm cách nào để người khác giải quyết vấn đề này? Vì dữ liệu phiên là trình duyệt pan, điều gì sẽ xảy ra nếu người dùng thực hiện cùng một thao tác nhiều giai đoạn song song trong hai tab hoặc cửa sổ của cùng một trình duyệt - chia sẻ cùng một dữ liệu phiên? – Mawg

+0

@Mawg: Chỉ cần lưu trữ dữ liệu trung gian trong các trường ẩn trong biểu mẫu. (xem [Câu trả lời của Wyzard] (http://stackoverflow.com/questions/7844415/x/7844704#7844704)) – icktoofay

2

Added kịch bản dưới đây sau khi tôi đăng nhập (nói dashboard.php)

<script> 
$(document).ready(function() 
{ 
    $("a").attr("target", ""); 
    if(typeof(Storage)    !== "undefined") 
    { 
     sessionStorage.pagecount = 1; 
     var randomVal    = Math.floor((Math.random() * 10000000) + 1); 
     window.name     = randomVal; 
     var url      = "url to update the value in db(say random_value)"; 
     $.post(url, function (data, url) 
     { 
     }); 
    } 
    else 
    { 
     var url      = "url to remove random_value";   
     $.post(url, function (data, url) 
     { 
      sessionStorage.removeItem('pagecount'); 
      sessionStorage.clear(); 
      window.location   = 'logout.php'; 
     }); 
    }  
}); 
</script> 

Added kịch bản dưới đây trong Header trong phần còn lại của các trang của tôi - 'random_value' là từ db cho người dùng đó

<script> 
$(document).ready(function() 
{  
    $("a").attr("target", "_self"); 

    if(typeof(Storage)      !== "undefined") 
    { 
     if (sessionStorage.pagecount) 
     { 
      if('<?=$random_value?>'   == window.name) 
      { 
       sessionStorage.pagecount = Number(sessionStorage.pagecount) + 1; 
      } 
      else 
      { 
       var url      = "url to remove random_value";   
       $.post(url, function (data, url) 
       { 
        sessionStorage.removeItem('pagecount'); 
        sessionStorage.clear(); 
        window.location   = 'logout.php'; 
       }); 

      }    
     } 
     else 
     {   
      var url       = "url to remove random_value";   
      $.post(url, function (data, url) 
      { 
       sessionStorage.removeItem('pagecount'); 
       sessionStorage.clear(); 
       window.location    = 'logout.php'; 
      }); 
     } 
    } 
    else 
    { 
     var url        = "url to remove random_value";     
     $.post(url, function (data, url) 
     { 
      sessionStorage.removeItem('pagecount'); 
      sessionStorage.clear(); 
      window.location     = 'logout.php'; 
     }); 
    } 
}); 
</script> 
0

Nếu tôi đã làm điều này ngay bây giờ, tôi có thể sẽ mã một trang AngularJs ứng dụng (mặc dù bất kỳ hình thức Js sẽ làm).

Khi khởi động, hãy xem bộ nhớ cục bộ để gắn cờ. Nếu được đặt, từ chối bắt đầu, với thông điệp phù hợp, hãy đặt cờ & chạy ứng dụng.

Chắc chắn, một người dùng độc hại có thể giải quyết vấn đề này vì đây không phải là kiểm tra phía máy chủ, nhưng tôi sẽ từ chối hỗ trợ như vậy.

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