양식 재 제출 방지


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.