클라이언트 측에서 양식이 여러 번 제출되는 것을 방지하는 방법은 무엇입니까?


96

응답이 느리면 제출 버튼을 여러 번 클릭 할 수 있습니다.

이런 일이 발생하지 않도록 방지하는 방법은 무엇입니까?


4
질문 제목에 "클라이언트 측"을 입력 한 이유는 복제 제출을 시도하고 방지하는 클라이언트의 모든 솔루션이 100 % 안전하지 않으며 항상 서버 측에서 유효성 검사를 수행 해야한다는 것을 알고 있기 때문 입니다.
Paolo Bergantino

51
Paolo : 예, 완전한 데이터 보안에 관심이 있다면 서버 측에서 수행해야합니다. 그러나 때로는 한 번만 클릭하면 될 때 할머니가 제출 버튼을 두 번 클릭하지 못하도록 막고 싶을 때가 있습니다. 이 경우 자바 스크립트는 완벽합니다.
사이먼 이스트

1
첫 번째 요청이 완료되는 데 시간이 오래 걸리므로 두 번째 요청이 진행하지 않아야한다는 것을 알 수 있기 때문에 서버 측에서만 수행하는 것은 100 % 안전하지 않습니다.
igorsantos07 2015 년

하지 않습니다 쿠키 패턴을 더블 - 제출 도 mutliple 양식 제출을 방지 방지 CSRF 공격에?
Martin Thoma 19

답변:


99

이미 제출 된 양식에서 제출 이벤트를 비활성화하려면 눈에 잘 띄지 않는 자바 스크립트를 사용하십시오. 다음은 jQuery를 사용하는 예입니다.

편집 : 제출 버튼을 클릭하지 않고 양식을 제출하는 문제를 수정했습니다. 고마워, 이치 반.

$("body").on("submit", "form", function() {
    $(this).submit(function() {
        return false;
    });
    return true;
});

4
텍스트 상자에서 Enter를 눌러 양식을 제출하면 어떻게됩니까?
ichiban

2
당신은 심지어 필요 return true합니까? 초기 제출은 그것 없이도 작동해야한다고 생각합니다.
사이먼 이스트

return true생략하면 묵시적 이라고 생각합니다 .
Derek

15
눈에 띄지 않는 유효성 검사 및 MVC 로이 솔루션을 시도했습니다. JS가 먼저 호출되고 항상 false를 반환 한 다음 유효성 검사가 호출됩니다. 따라서 내 양식에 유효성 검사 오류가 있으면 양식이 제출되지 않습니다!
bjan 2012-06-08

6
정말 잘 작동합니다. 또한 제출 버튼을 비활성화하고 제출 버튼 텍스트를 교체하여 사용자 힌트도 표시하고 싶습니다. $(this).find("input[type='submit']").attr('disabled', 'disabled').val('submiting'); return true; });
Cam Song

42

asp mvc 3 unobtrusive validation과 함께 vanstee의 솔루션 을 시도 했으며 클라이언트 유효성 검사가 실패하면 코드가 계속 실행되고 양식 제출이 영구적 으로 비활성화됩니다. 필드를 수정 한 후 다시 제출할 수 없습니다. (bjan의 의견 참조)

그래서 vanstee의 스크립트를 다음과 같이 수정했습니다.

$("form").submit(function () {
    if ($(this).valid()) {
        $(this).submit(function () {
            return false;
        });
        return true;
    }
    else {
        return false;
    }
});

주의해야 할 다른 부작용이 있습니까? 아니면 모든 곳에 적용 할 수 있습니까?
시아 란 갤러거

24

클라이언트 측 양식 제출 제어는 onsubmit 핸들러가 제출 단추를 숨기고로드 애니메이션으로 대체함으로써 매우 우아하게 달성 할 수 있습니다. 이렇게하면 사용자가 자신의 행동 (클릭)이 발생한 지점에서 즉각적인 시각적 피드백을받을 수 있습니다. 동시에 양식이 다른 시간에 제출되는 것을 방지합니다.

XHR을 통해 양식을 제출하는 경우 제출 오류 (예 : 시간 초과)도 처리해야합니다. 사용자 양식 다시 제출 해야 하므로 제출 단추를 다시 표시해야합니다 .

또 다른 메모에서 llimllib는 매우 유효한 지점을 제시합니다. 모든 양식 유효성 검사는 서버 측에서 발생해야합니다. 여기에는 여러 제출 확인이 포함됩니다. 클라이언트를 신뢰하지 마십시오! 자바 스크립트가 비활성화 된 경우에만 해당되는 것은 아닙니다. 모든 클라이언트 측 코드를 수정할 수 있음을 명심해야합니다. 상상하기는 다소 어렵지만 서버와 대화하는 html / javascript가 반드시 작성한 html / javascript가 아닐 수 있습니다.

llimllib가 제안한대로 해당 양식에 대해 고유 한 식별자로 양식을 생성하고 숨겨진 입력 필드에 넣습니다. 그 식별자를 저장하십시오. 양식 데이터를 수신 할 때 식별자가 일치 할 때만 처리합니다. (또한 추가 보안을 위해 식별자를 사용자 세션에 연결하고 일치시킵니다.) 데이터 처리 후 식별자를 삭제합니다.

물론 가끔 양식 데이터가 제출되지 않은 식별자를 정리해야합니다. 그러나 아마도 귀하의 웹 사이트는 이미 일종의 "가비지 수집"메커니즘을 사용하고있을 것입니다.


15
<form onsubmit="if(submitted) return false; submitted = true; return true">

6
를 사용 <form onsubmit="return (typeof submitted == 'undefined') ? (submitted = true) : !submitted">하거나 var submitted = false;스크립트의 올바른 지점에 작성하여 다음 오류를 방지하십시오 Uncaught ReferenceError: submitted is not defined..
Tamás Bolvári 2014

15

이를 수행하는 간단한 방법은 다음과 같습니다.

<form onsubmit="return checkBeforeSubmit()">
  some input:<input type="text">
  <input type="submit" value="submit" />
</form>

<script type="text/javascript">
  var wasSubmitted = false;    
    function checkBeforeSubmit(){
      if(!wasSubmitted) {
        wasSubmitted = true;
        return wasSubmitted;
      }
      return false;
    }    
</script>

jQuery의 눈에 거슬리지 않는 유효성 검사를 사용하면 차단 스크립트가 먼저 호출되고 유효성 검사가 다음에는 유효성 검사 오류가있는 경우 제출이 전혀 발생하지 않습니다
bjan

8

클릭 직후 제출 버튼을 비활성화하십시오. 유효성 검사를 올바르게 처리해야합니다. 또한 모든 처리 또는 DB 작업을위한 중간 페이지를 유지하고 다음 페이지로 리디렉션합니다. 이렇게하면 두 번째 페이지를 새로 고침해도 다른 처리가 수행되지 않습니다.


예, 훌륭한 팁 Shoban, 동의합니다. 이어야한다form page ---submits to---> form_submission_script.php ---after saving, redirects to---> form_thankyou.html
사이먼 동

6

현재 시간을 해시하고 양식에 숨겨진 입력으로 만듭니다. 서버 측에서 각 양식 제출의 해시를 확인하십시오. 이미 해당 해시를 받았다면 반복 제출이있는 것입니다.

편집 : 자바 스크립트에 의존하는 것은 좋은 생각이 아니므로 모든 사람들이 계속해서 그 아이디어를 찬성 할 수 있지만 일부 사용자는이를 활성화하지 않을 것입니다. 정답은 서버 측에서 사용자 입력을 신뢰하지 않는 것입니다.


"너무 많이"보이지 않습니까? ;-)
Shoban

1
사용자가 초당 한 번 이상 양식을 제출하지 못하게하는 것처럼 들립니다. 2009-05-29 12:13:37에 양식을 제출하면 서버에서 동일한 해시로 다른 양식을 제출할 수 없지만 2009-05-29 12:13:38에 제출을 클릭하면 통과 할 것입니다. 또한, 당신의 기술은 두 명의 다른 사용자가 동시에 두 가지 다른 양식을 제출하는 것을 막을 것입니다. 그 중 하나는 그 사람의 첫 번째 제출 일지라도 그 중 하나는 추방 될 것입니다.
Sarah Vessels

2
@moneypenny 귀하의 첫 번째 이의는 거짓입니다. 해시는 사용자가 제출 한 시간이 아니라 양식이 사용자에게 전송 된 시간입니다. 두 번째에 대해 진정으로 걱정한다면 다양한 옵션이 있습니다. 해시 한 문자열에 세션 ID를 추가하고 / 또는 양식의 모든 필드가 정확한지 확인하십시오. 두 명의 사용자가 정확히 동일한 양식을 제출하지 않았을 것입니다.
llimllib

@Shoban 미안 해요, 당신이하는 말을 따르지 않습니다
llimllib

2
"과도한"은 보는 사람의 눈에 있습니다. 당신이 경우 정말 솔루션의 적어도 일부에서 중복 폼 제출을 방지 할 필요가 서버 측이어야한다. "사용자를 믿을 수 없습니다."
Ben Blank

5

진행률 표시 줄이나 스피너를 표시하여 양식이 처리 중임을 나타낼 수도 있습니다.


5

JQuery를 사용하면 다음을 수행 할 수 있습니다.

$('input:submit').click( function() { this.disabled = true } );

&

   $('input:submit').keypress( function(e) {
     if (e.which == 13) {
        this.disabled = true 
     } 
    }
   );

1
버튼이 비활성화 된 후 텍스트 상자에서 Enter 키를 눌러 양식을 제출하면 어떻게됩니까?
ichiban

이와 같은 버튼을 비활성화하면 사용자가 ENTER를 누를 수 없습니다. 하지만 제출 입력에 키 누르기를 바인딩해야합니다
Boris Guéry

이렇게하면 버튼이 제출되지 않습니다. 따라서 서버 측 유효성 검사를 비활성화합니다.
Marko Aleksić 2011 년

@Marko, 맞아요.하지만 OP가 요청한 것입니다. 어쨌든 토큰을 사용하면 양식이 두 번 제출되지 않습니다.
Boris Guéry 2011 년

1
이런 종류의 기술을 시도했을 때 브라우저가 양식 제출을 시작하기 전에 버튼을 비활성화했기 때문에 양식이 전혀 제출되지 않는다는 것을 발견했습니다 (적어도 Chrome 14에서는 그렇지 않음).
사이먼 이스트

4

질문에 'javascript'태그를 붙인 것을 알고 있지만 여기에 자바 스크립트에 전혀 의존하지 않는 해결책이 있습니다.

PRG 라는 웹앱 패턴 이며 여기에 이를 설명 하는 좋은 기사 가 있습니다.


4

다음과 같이 간단하게 여러 제출을 방지 할 수 있습니다.

var Workin = false;

$('form').submit(function()
{
   if(Workin) return false;
   Workin =true;

   // codes here.
   // Once you finish turn the Workin variable into false 
   // to enable the submit event again
   Workin = false;

});

답변의 문제는 사용자가 클릭하는 시간과 시간 사이에 1 초가 걸린다는 것 Workin =true;입니다. 이중 제출은 여전히 ​​가능하지만 더 적은 가능성이 있습니다.
sent1nel 2014

4

이 질문에 대한 가장 간단한 대답은 다음과 같습니다. "응답이 느릴 때 제출 버튼을 여러 번 클릭 할 수 있습니다.이 문제를 방지하는 방법은 무엇입니까?"

아래 코드와 같이 양식 제출 버튼을 비활성화하십시오.

<form ... onsubmit="buttonName.disabled=true; return true;">
  <input type="submit" name="buttonName" value="Submit">
</form>

제출을 위해 처음 클릭하면 제출 버튼이 비활성화됩니다. 또한 몇 가지 유효성 검사 규칙이 있으면 제대로 작동합니다. 도움이되기를 바랍니다.


나는 당신이 뭔가를 놓친 것 같아 코드를 게시하십시오.
Imran Khan

3

클라이언트 측에서는 @vanstee 및 @chaos에서 제공하는 방법과 같이 자바 스크립트 코드로 양식이 제출되면 제출 버튼을 비활성화해야합니다.

그러나 네트워크 지연이나 자바 스크립트 사용이 불가능한 상황에 대한 문제가있어이를 방지하기 위해 JS에 의존해서는 안됩니다.

따라서 서버 측에서는 동일한 클라이언트의 반복 제출을 확인하고 사용자의 잘못된 시도로 보이는 반복 된 제출을 생략해야합니다.


나는 이것이 오래 전에 대답했다는 것을 알고 있지만 누군가 네트워크 지연이 비활성화를 방지하는 방법을 설명 할 수 있습니까? 나는 지금이 문제를 다루고 있으며 버튼을 비활성화하더라도 양식이 어떻게 이중 제출되었는지에 대해 매우 혼란 스럽습니다. 나는 JavaScript가 비활성화 된 것에 대해 생각조차하지 않았습니다. 제 경우에는 그것이 문제라고 생각하지 않지만 그럼에도 불구하고 흥미로운 통찰력입니다.
davidatthepark

또한 클릭 핸들러 조절을 고려하고있었습니다.
davidatthepark

동일한 클라이언트에서 제출하는 경우 서버 측을 어떻게 확인합니까? 사용자 IP 주소로? 그렇다면 이전에 제출 한 항목의 서버 측 IP 주소를 어디에 "저장"하시겠습니까? (컨텍스트가 필요한 경우 노드를 사용하고 있습니다)
user1063287

3

safeform jquery 플러그인을 사용해 볼 수 있습니다 .

$('#example').safeform({
    timeout: 5000, // disable form on 5 sec. after submit
    submit: function(event) {
        // put here validation and ajax stuff...

        // no need to wait for timeout, re-enable the form ASAP
        $(this).safeform('complete');
        return false;
    }
})

1

나를위한 가장 간단하고 우아한 솔루션 :

function checkForm(form) // Submit button clicked
{
    form.myButton.disabled = true;
    form.myButton.value = "Please wait...";
    return true;
}

<form method="POST" action="..." onsubmit="return checkForm(this);">
    ...
    <input type="submit" name="myButton" value="Submit">
</form>

추가 링크 ...


1

양식에서이 코드를 사용하면 여러 번의 클릭을 처리합니다.

<script type="text/javascript">
    $(document).ready(function() {
        $("form").submit(function() {
            $(this).submit(function() {
                return false;
            });
            return true;
        });     
    }); 
</script>

확실히 작동합니다.


1

2 초마다 제출할 수 있습니다. 전면 검증의 경우.

$(document).ready(function() {
    $('form[debounce]').submit(function(e) {
        const submiting = !!$(this).data('submiting');

        if(!submiting) {
            $(this).data('submiting', true);

            setTimeout(() => {
                $(this).data('submiting', false);
            }, 2000);

            return true;
        }

        e.preventDefault();
        return false;
    });
})

0

다중 제출을 방지하는 가장 좋은 방법은 메서드에 버튼 ID를 전달하는 것입니다.

    function DisableButton() {
        document.getElementById("btnPostJob").disabled = true;
    }
    window.onbeforeunload = DisableButton; 

0

자바 스크립트를 사용하여이 작업을 수행하는 것은 약간 쉽습니다. 다음은 원하는 기능을 제공하는 코드입니다.

$('#disable').on('click', function(){
    $('#disable').attr("disabled", true);
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="disable">Disable Me!</button>


0

가장 간단한 해결책은 클릭시 버튼을 비활성화하고 작업이 완료된 후 활성화하는 것입니다. jsfiddle에서 유사한 솔루션을 확인하려면 다음을 수행하십시오.

[click here][1]

그리고이 답변에 대한 다른 해결책을 찾을 수 있습니다 .


1
링크는 훌륭하지만 답변 에는 실제로 답변 이 포함되어야 하므로 링크에 대한 컨텍스트를 제공하세요 . 외부 사이트에 대한 링크지나지 않는 것이 일부 답변이 삭제 되는 이유와 방법에 대한 가능한 이유입니다 . .
Jan

0

이것은 나를 위해 매우 잘 작동합니다. 농장을 제출하고 버튼을 비활성화하고 2 초 후에 버튼을 활성화합니다.

<button id="submit" type="submit" onclick="submitLimit()">Yes</button>

function submitLimit() {
var btn = document.getElementById('submit')
setTimeout(function() {
    btn.setAttribute('disabled', 'disabled');
}, 1);

setTimeout(function() {
    btn.removeAttribute('disabled');
}, 2000);}

ECMA6 Syntex에서

function submitLimit() {
submitBtn = document.getElementById('submit');

setTimeout(() => { submitBtn.setAttribute('disabled', 'disabled') }, 1);

setTimeout(() => { submitBtn.removeAttribute('disabled') }, 4000);}

0

브라우저 입력 유효성 검사를 우회하지 않고 가능한 답변을 추가하기 위해

$( document ).ready(function() {
    $('.btn-submit').on('click', function() {
        if(this.form.checkValidity()) {
            $(this).attr("disabled", "disabled");
            $(this).val("Submitting...");
            this.form.submit();
        }
    });
});

0

이전에 제안 된 것에 대한 대안은 다음과 같습니다.

jQuery('form').submit(function(){
     $(this).find(':submit').attr( 'disabled','disabled' );
     //the rest of your code
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.