2010-10-13 49 views
89

Trang một chứa biểu mẫu HTML. Trang hai - mã xử lý dữ liệu đã gửi.Ngăn gửi lại biểu mẫu

Biểu mẫu trong trang một được gửi. Trình duyệt được chuyển hướng đến trang hai. Trang hai xử lý dữ liệu đã gửi.

Tại thời điểm này, nếu trang hai được làm mới, thông báo "Xác nhận gửi lại biểu mẫu" sẽ bật lên.

Điều này có thể được ngăn chặn không?

+0

Sử dụng một hộp thoại xác nhận: http://stackoverflow.com/questions/6457750/form-confirm-before-submit/12357337#12357337 –

+3

sử dụng bài redirect được như mô tả ở đây - >> http://en.wikipedia.org/wiki/Post/Redirect/Get – Meer

+0

Bạn có thể ngăn chặn điều đó ngay cả khi không chuyển hướng. Nhìn [ở đây] (https://stackoverflow.com/a/47247434/4632019) –

Trả lời

131

Có 2 phương pháp tiếp cận người sử dụng để chụp ở đây:

Phương pháp 1: Sử dụng AJAX + Chuyển

Bằng cách này bạn gửi mẫu của bạn ở chế độ nền sử dụng JQuery hoặc một cái gì đó tương tự như Page2, trong khi người dùng vẫn thấy trang 1 được hiển thị. Sau khi đăng thành công, bạn chuyển hướng trình duyệt đến Trang2.

Cách 2: bài + Chuyển tới tự

Đây là một kỹ thuật phổ biến trên các diễn đàn. Biểu mẫu trên Page1 đăng dữ liệu lên Page2, Page2 xử lý dữ liệu và thực hiện những gì cần phải được thực hiện, và sau đó nó thực hiện chuyển hướng HTTP trên chính nó. Bằng cách này "hành động" cuối cùng mà trình duyệt nhớ là một GET đơn giản trên page2, do đó biểu mẫu không được gửi lại khi F5.

+2

Một biến thể của phương pháp 2 là một chuyển hướng đến một trang khác. Ví dụ: bạn POST tới http://example.com/save.html và sau khi lưu xong, bạn chuyển hướng đến http://example.com/list.html. – Guillaume

+1

Với phương pháp 1, tôi muốn sử dụng plugin jQuery có tên BlockUI để cho khách hàng biết điều gì đó đang xảy ra. – Shikiryu

+0

Tôi đang sử dụng phương pháp 2 nhưng nó yêu cầu tôi gửi lại lần nữa Nếu tôi làm mới. Bất cứ ai có vấn đề tương tự với điều này? – keen

9

Trực tiếp, bạn không thể, và đó là một điều tốt. Cảnh báo của trình duyệt có lý do. chủ đề này nên trả lời câu hỏi của bạn:

Prevent Back button from showing POST confirmation alert

Hai cách giải quyết chính đề nghị là mô hình PRG, và một AJAX submit theo sau là một di dời kịch bản.

Lưu ý rằng nếu phương pháp của bạn cho phép GET và không phải là phương thức gửi POST, thì cả hai đều sẽ giải quyết được vấn đề và phù hợp hơn với quy ước. Các giải pháp đó được cung cấp dựa trên giả định bạn muốn/cần gửi dữ liệu.

2

Nếu bạn làm mới trang có dữ liệu POST, trình duyệt sẽ xác nhận việc gửi lại của bạn. Nếu bạn sử dụng dữ liệu GET, thông báo sẽ không được hiển thị. Bạn cũng có thể có trang thứ hai, sau khi lưu nội dung gửi, chuyển hướng đến trang thứ ba không có dữ liệu.

6

Cách duy nhất để đảm bảo 100% cùng một biểu mẫu không bao giờ được gửi hai lần là nhúng mã định danh duy nhất vào mỗi mã bạn phát hành và theo dõi những biểu mẫu nào đã được gửi tại máy chủ. Điều đáng tiếc là nếu người dùng sao lưu vào trang có biểu mẫu và nhập dữ liệu mới, cùng một biểu mẫu sẽ không hoạt động.

6

Có hai phần để câu trả lời:

  1. Đảm bảo bài viết trùng lặp không gây rối với dữ liệu của bạn ở phía máy chủ. Để thực hiện việc này, hãy nhúng một số nhận dạng duy nhất vào bài đăng để bạn có thể từ chối các yêu cầu tiếp theo phía máy chủ. Mẫu này được gọi là Máy nhận Idempotent trong điều khoản nhắn tin.

  2. Đảm bảo người dùng không được làm phiền bởi những khả năng của lần gửi bản sao của cả hai

    • chuyển hướng đến một GET sau khi POST (POST redirect GET mẫu)
    • vô hiệu hóa các nút sử dụng javascript

Không có gì bạn làm dưới 2. hoàn toàn sẽ ngăn các lần gửi trùng lặp. Mọi người có thể nhấp vào rất nhanh và tin tặc có thể đăng bài. Bạn luôn luôn cần 1. nếu bạn muốn hoàn toàn chắc chắn không có bản sao.

-2

Tôi đang sử dụng Chrome và bạn có thể làm điều này ...

1), bạn có thể sử dụng trên trang đó các mẫu được submiting:

<?php 
    if(isset($_POST['yourpost'])){ 
     //your codes go here 
     //in the end of this lines you will do this: 
     header("Location: this same page.php"); 
     exit; 
    } 
    else{ 
     //do nothing 
    } 
?> 

MÃ HTML CỦA BẠN LÀ DƯỚI

<html>....</html> 
+0

nếu bạn gửi lại biểu mẫu mảng POST sẽ chứa dữ liệu :) – daslicht

16

Bạn cần sử dụng PRG - Đăng/Chuyển hướng/Lấy mẫu và bạn vừa triển khai P của PRG. Bạn cần phải Chuyển hướng. (Hiện tại, bạn không cần chuyển hướng chút nào. Hãy xem this)

PRG là mẫu thiết kế phát triển web ngăn chặn một số bản sao gửi biểu mẫu có nghĩa là, Gửi biểu mẫu (Gửi yêu cầu 1) -> Chuyển hướng -> Nhận (Yêu cầu) 2)

Under the hood 

Redirect mã trạng thái - HTTP 1.0 với HTTP 302 hoặc HTTP 1.1 với HTTP 303

một phản ứng HTTP với mã trạng thái chuyển hướng bổ sung sẽ cung cấp một URL trong lĩnh vực tiêu đề địa điểm. Tác nhân người dùng (ví dụ: trình duyệt web) được mời bằng phản hồi với mã này để thực hiện yêu cầu thứ hai, nếu không giống hệt, yêu cầu đến URL mới được chỉ định trong trường vị trí.

Mã trạng thái chuyển hướng là để đảm bảo rằng trong trường hợp này, trình duyệt của người dùng web có thể làm mới một cách an toàn phản hồi của máy chủ mà không làm cho yêu cầu HTTP POST ban đầu được gửi lại.

Double Submit Problem 

Double Submit Problem

Post/Redirect/Get Solution 

Post/Redirect/Get Solution

Source

+2

Giải thích tốt. Tôi tự hỏi điều gì sẽ xảy ra nếu người dùng nhấp vào nút quay lại trên trình duyệt sau khi chuyển hướng được thực hiện. Sẽ hiển thị lại "xác nhận gửi lại biểu mẫu" lại không. Tôi đoán ngay cả khi cửa sổ xác nhận không hiển thị lại, yêu cầu đăng trên trang 1 có cùng dữ liệu được thực hiện lại và một lần nữa người dùng sẽ được chuyển hướng đến trang 2. Tôi có một loạt biểu mẫu, form1, form2, form3. làm thế nào có thể quay trở lại từ hình thức "n" để tạo thành "n-1" liền mạch. Câu hỏi ngẫu nhiên: Bạn đã nghiên cứu mẫu thiết kế PRG ở đâu – Rpant

+0

@Rpant trên chrome tệp php gửi tiêu đề vị trí thậm chí không hiển thị trong lịch sử trình duyệt, do đó, nút quay lại sẽ đưa bạn trở lại biểu mẫu. – FluorescentGreen5

+0

@Angelin Sau khi chuyển hướng cách nhận dữ liệu? Ví dụ: khi tôi đăng một số dữ liệu lên/some_url và chuyển hướng đến/some_url, tạo yêu cầu GET. Làm cách nào để biết phản hồi là/some_url là gì chung và không kết hợp id như/some_url/? –

0

Các mô hình PRG chỉ có thể ngăn chặn sự nộp lại do trang làm mới. Đây không phải là biện pháp an toàn 100%.

Thông thường, tôi sẽ có những hành động dưới đây để ngăn chặn nộp lại:

  1. Client Side - Sử dụng javascript để ngăn chặn các bấm đúp vào một nút đó sẽ kích hoạt trình đơn.Bạn chỉ có thể tắt nút sau lần nhấp đầu tiên.

  2. Phía máy chủ - Tôi sẽ tính giá trị băm trên các tham số đã gửi và lưu băm đó trong phiên hoặc cơ sở dữ liệu, vì vậy khi chúng tôi nhận được bản sao, chúng tôi có thể phát hiện trùng lặp rồi trả lời đúng cho máy khách. Tuy nhiên, bạn có thể quản lý để tạo ra một băm ở phía khách hàng.

Trong hầu hết các trường hợp, các biện pháp này có thể giúp ngăn chặn gửi lại.

1

Tôi thấy không ai đề cập đến mẹo này.

Nếu không có chuyển hướng, bạn vẫn có thể ngăn xác nhận biểu mẫu khi làm mới.

Theo mặc định, mẫu mã là như thế này:

<form method="post" action="test.php">

bây giờ, thay đổi nó để <form method="post" action="test.php?nonsense=1">

Bạn sẽ thấy sự kỳ diệu.

Tôi đoán vì trình duyệt sẽ không kích hoạt cửa sổ bật lên cảnh báo xác nhận nếu nó nhận được phương thức GET (chuỗi truy vấn) trong url.

0

Tôi thực sự thích câu trả lời của @ Angelin. Nhưng nếu bạn đang đối phó với một số mã di sản mà điều này là không thực tế, kỹ thuật này có thể làm việc cho bạn.

Ở phía trên cùng của tập tin

// Protect against resubmits 
if (empty($_POST)) { 
    $_POST['last_pos_sub'] = time(); 
} else { 
    if (isset($_POST['last_pos_sub'])){ 
     if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) { 
      redirect back to the file so POST data is not preserved 
     } 
     $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub']; 
    } 
} 

Sau đó, ở phần cuối của hình thức, gắn bó trong last_pos_sub như sau:

<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>> 
0

Hãy thử tris:

function prevent_multi_submit($excl = "validator") { 
    $string = ""; 
    foreach ($_POST as $key => $val) { 
    // this test is to exclude a single variable, f.e. a captcha value 
    if ($key != $excl) { 
     $string .= $key . $val; 
    } 
    } 
    if (isset($_SESSION['last'])) { 
    if ($_SESSION['last'] === md5($string)) { 
     return false; 
    } else { 
     $_SESSION['last'] = md5($string); 
     return true; 
    } 
    } else { 
    $_SESSION['last'] = md5($string); 
    return true; 
    } 
} 

Làm thế nào để sử dụng/ví dụ:

if (isset($_POST)) { 
    if ($_POST['field'] != "") { // place here the form validation and other controls 
    if (prevent_multi_submit()) { // use the function before you call the database or etc 
     mysql_query("INSERT INTO table..."); // or send a mail like... 
     mail($mailto, $sub, $body); // etc 
    } else { 
     echo "The form is already processed"; 
    } 
    } else { 
    // your error about invalid fields 
    } 
} 

Font: https://www.tutdepot.com/prevent-multiple-form-submission/

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