양식 재 제출 방지


107

페이지 1에는 HTML 양식이 있습니다. 2 페이지-제출 된 데이터를 처리하는 코드.

1 페이지의 양식이 제출됩니다. 브라우저가 2 페이지로 리디렉션됩니다. 2 페이지는 제출 된 데이터를 처리합니다.

이 시점에서 페이지 2가 새로 고쳐지면 "양식 재 제출 확인"경고가 나타납니다.

이를 방지 할 수 있습니까?



3
여기에 설명 된대로 post redirect get 사용->> en.wikipedia.org/wiki/Post/Redirect/Get
Meer

리디렉션 없이도이를 방지 할 수 있습니다. 봐 여기에
오이겐 Konkov에게

답변:


145

사람들이 여기에서 사용하는 두 가지 접근 방식이 있습니다.

방법 1 : AJAX + 리디렉션 사용

이렇게하면 JQuery 또는 Page2와 유사한 것을 사용하여 백그라운드에서 양식을 게시하는 반면 사용자는 여전히 page1이 표시된 것을 볼 수 있습니다. 게시에 성공하면 브라우저를 Page2로 리디렉션합니다.

방법 2 : 게시 + 자신에게 리디렉션

이것은 포럼에서 일반적인 기술입니다. 페이지 1의 양식은 페이지 2에 데이터를 게시하고, 페이지 2는 데이터를 처리하고 필요한 작업을 수행 한 다음 자체적으로 HTTP 리디렉션을 수행합니다. 이렇게하면 브라우저가 기억하는 마지막 "작업"은 page2의 간단한 GET이므로 F5시 양식이 다시 제출되지 않습니다.


2
방법 2의 변형은 다른 페이지로 리디렉션하는 것입니다. 예를 들어 example.com/save.html에 POST 하고 저장이 완료되면 example.com/list.html로 리디렉션됩니다 .
Guillaume

1
방법 1에서는 BlockUI라는 jQuery 플러그인을 사용하여 클라이언트에게 어떤 일이 발생하고 있음을 알립니다.
Shikiryu

방법 2를 사용하고 있지만 새로 고치면 다시 제출하라는 메시지가 표시됩니다. 누구든지 이것과 비슷한 문제가 있습니까?
예리한

HTTP 리디렉션이 제대로 작동하고 있습니까? 나가는 HTTP 요청을 검사하기 위해 브라우저에있는 네트워크 검사기 / 방화범 / 방화벽을 열고 HTTP 호출을 확인합니다. POST 메서드에서 발생하는 첫 번째 항목 (양식 데이터 게시)을보고 Location 헤더가 자신을 가리키는 HTTP 코드 301을 반환 한 다음 즉시 GET 메서드를 사용하여 동일한 페이지에 대한 다른 HTTP 쿼리를 볼 수 있어야합니다.
CodeTwice

@CodeTwice : 제 경우에는 page1이 page2에 게시하고, page2는 데이터를 처리하고 페이지를 표시합니다 (값이 템플릿에 전달됨) .. 어디에서 리디렉션이 발생해야합니까? .. 페이지에 GET 요청이 없습니다.
user1050619

24

PRG-Post / Redirect / Get 패턴을 사용해야 하며 방금 PRG의 P를 구현했습니다. 리디렉션 해야합니다 . (지금은 리디렉션이 전혀 필요하지 않습니다. 참조 하십시오 )

PRG는 양식 제출 (Post Request 1)-> Redirect-> Get (Request 2)를 의미하는 일부 중복 양식 제출을 방지하는 웹 개발 디자인 패턴입니다.

Under the hood

리디렉션 상태 코드 -HTTP 302를 사용하는 HTTP 1.0 또는 HTTP 303을 사용하는 HTTP 1.1

리디렉션 상태 코드가있는 HTTP 응답은 위치 헤더 필드에 URL을 추가로 제공합니다. 사용자 에이전트 (예 : 웹 브라우저)는이 코드가있는 응답에 의해 초대되어 위치 필드에 지정된 새 URL에 대해 동일한 두 번째 요청을합니다.

리디렉션 상태 코드는이 상황에서 웹 사용자의 브라우저가 초기 HTTP POST 요청을 다시 제출하지 않고도 서버 응답을 안전하게 새로 고칠 수 있도록하는 것입니다.

Double Submit Problem

이중 제출 문제

Post/Redirect/Get Solution

게시 / 리디렉션 / 솔루션 얻기

출처


2
좋은 설명입니다. 리디렉션이 이루어진 후 사용자가 브라우저에서 뒤로 버튼을 클릭하면 어떻게 될지 궁금합니다. "양식 재 제출 확인"팝업이 다시 표시됩니까? 확인 팝업이 다시 표시되지 않더라도 동일한 데이터로 1 페이지에 게시 요청이 다시 생성되고 다시 한 번 사용자가 2 페이지로 리디렉션됩니다. 일련의 양식, form1, form2, form3이 있습니다. 어떻게 "n"형태에서 "n-1"형태로 원활하게 되돌아 갈 수 있습니까? 무작위 질문 : 당신은 PRG 디자인 패턴 연구 않았다
Rpant

@Rpant on chrome 위치 헤더를 보내는 PHP 파일은 브라우저 기록에도 표시되지 않으므로 뒤로 버튼을 누르면 양식으로 돌아갑니다.
FluorescentGreen5

@Angelin 리디렉션 후 데이터를 얻는 방법은 무엇입니까? 예를 들어 일부 데이터를 / some_url에 게시하고 GET 요청을 만드는 / some_url로 리디렉션합니다. / some_url이 일반적이고 / some_url / <id>와 같은 ID를 포함하지 않으므로 응답이 무엇인지 어떻게 알 수 있습니까?
Amit Tripathi

@AmitTripathi는 직접 만들어야합니다. 예 : POST 요청은 고객 데이터를 삽입 할 수있는 반면 GET은 성공적으로 삽입 된 데이터를 표시합니다. 데이터를 양식 데이터로 표시하거나 데이터베이스에 성공적으로 삽입 한 후받은 고객 ID로 해당 고객에 대한 데이터베이스에서 가져 와서 고객 페이지의보기를 재사용 할 수 있습니다.
Angelin Nadar

하지만 @Eugen Konkov 솔루션에 동의합니다
Angelin Nadar

10

직접적으로 할 수 없습니다. 그것은 좋은 일입니다. 브라우저의 경고는 이유가 있습니다. 이 스레드는 귀하의 질문에 답할 것입니다.

뒤로 버튼이 POST 확인 경고를 표시하지 않도록 방지

제안 된 두 가지 주요 해결 방법은 PRG 패턴과 AJAX 제출 후 스크립팅 재배치였습니다.

메서드가 POST 제출 메서드가 아닌 GET을 허용하는 경우 문제가 해결되고 규칙에 더 적합합니다. 이러한 솔루션은 POST 데이터를 원하거나 필요로한다는 가정하에 제공됩니다.


8

동일한 양식이 두 번 제출되지 않도록 100 % 확신 할 수있는 유일한 방법은 발행하는 각 양식에 고유 식별자를 포함하고 서버에 제출 된 양식을 추적하는 것입니다. 함정은 사용자가 양식이 있던 페이지로 백업하고 새 데이터를 입력하면 동일한 양식이 작동하지 않는다는 것입니다.


6

답변에는 두 부분이 있습니다.

  1. 중복 게시물이 서버 측의 데이터를 엉망으로 만들지 않도록하십시오. 이렇게하려면 후속 요청 서버 측을 거부 할 수 있도록 게시물에 고유 식별자를 포함합니다. 이 패턴은 을 메시징 용어로 Idempotent Receiver 합니다.

  2. 사용자가 둘 다에 의한 중복 제출 가능성으로 인해 방해받지 않도록하십시오.

    • POST 후 GET으로 리디렉션 (POST 리디렉션 GET 패턴)
    • 자바 스크립트를 사용하여 버튼 비활성화

2 미만으로 수행하는 작업은 중복 제출을 완전히 방지하지 않습니다. 사람들은 매우 빠르게 클릭 할 수 있으며 해커는 어쨌든 게시 할 수 있습니다. 중복이 없는지 절대적으로 확인하려면 항상 1이 필요합니다.


2

POST 데이터로 페이지를 새로 고치면 브라우저가 다시 제출을 확인합니다. GET 데이터를 사용하는 경우 메시지가 표시되지 않습니다. 제출을 저장 한 후 데이터가없는 세 번째 페이지로 리디렉션되는 두 번째 페이지를 가질 수도 있습니다.


2

아무도이 속임수를 언급하지 않았다는 것을 알았습니다.

리디렉션 없이도 새로 고칠 때 양식 확인을 방지 할 수 있습니다.

기본적으로 양식 코드는 다음과 같습니다.

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

지금, 그것을 <form method="post" action="test.php?nonsense=1">

당신은 마법을 보게 될 것입니다.

URL에 GET 메서드 (쿼리 문자열)를 가져 오면 브라우저가 확인 경고 팝업을 트리거하지 않기 때문이라고 생각합니다.


2

jquery를 사용하여 수행 할 수 있습니다.

<script>
   $(document).ready(function(){
   window.history.replaceState('','',window.location.href)
   });
</script>

이것은 포스트 백으로 인해 제출 후 데이터를 다시 방지하는 가장 우아한 방법입니다.

도움이 되었기를 바랍니다.


0

PRG 패턴은 페이지 새로 고침으로 인한 다시 제출을 막을 수만 있습니다. 이것은 100 % 안전한 조치가 아닙니다.

일반적으로 다시 제출하지 않도록 다음과 같은 조치를 취하겠습니다.

  1. 클라이언트 측-양식 제출을 트리거하는 버튼에 대한 중복 클릭을 방지하려면 javascript를 사용하십시오. 첫 번째 클릭 후에 버튼을 비활성화 할 수 있습니다.

  2. 서버 측-제출 된 매개 변수에 대한 해시를 계산하고 해당 해시를 세션 또는 데이터베이스에 저장하므로 중복 제출이 수신되면 중복을 감지 한 다음 클라이언트에 적절한 응답을 할 수 있습니다. 그러나 클라이언트 측에서 해시를 생성하도록 관리 할 수 ​​있습니다.

대부분의 경우 이러한 조치는 재 제출을 방지하는 데 도움이 될 수 있습니다.


0

@Angelin의 대답을 정말 좋아합니다. 그러나 이것이 실용적이지 않은 레거시 코드를 다루는 경우이 기술이 적합 할 수 있습니다.

파일 상단

// 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'];
     }
}

그런 다음 양식 끝에 last_pos_sub다음과 같이 입력하십시오.

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

0

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

사용 방법 / 예 :

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

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


0

데이터 추가를 방지하려면 js를 사용하십시오.

if ( window.history.replaceState ) {
    window.history.replaceState( null, null, window.location.href );
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.