Asked Jul 9th, 3:42 PM 196 0 3
  • 196 0 3
+1

Làm sao để ngăn người dùng nhấn submit form nhiều lần ?

Share
  • 196 0 3

Mình có một cái form nhưng không làm sao ngăn người dùng submit nhiều lần được. Có tìm hiểu trên mạng thì có vài ý kiến.

  1. Dùng javascript disable button, form ... cách này không ổn vì nó chỉ giải quyết phía client sẽ ko triệt để được .
  2. Xử lý phía sever . đây là cách mình cần dùng nhưng chưa thể làm triệt để được.

Trong Laravel mình tham khảo cách này nhưng cũng ko ngăn được họ click nhiều lần.

File Controller

public function postTest(Request $r){
	if($r->form_token != session('form_token'))
	{
		echo '<br/> Access denied';
	} else {
		echo '<br/> Work';
		$px = new PhieuXuat();
		$px->author = session('ID');
		$px->title =  session('form_token') ;
		$px->khohang =  $r->form_token ; 
		$px->tinh =  $r->name ; 
 		$px->save();
	}

	$this->chuongtrinhA();
	$this->chuongtrinhB();
	$this->chuongtrinhC();
	Session::put('form_token', '');
}

public function chuongtrinhA(){
		$px = new PhieuXuat();
		$px->author = 11;
		$px->title =  'TitleAAA'; 
  		$px->save();
}public function chuongtrinhB(){
		$px = new PhieuXuat();
		$px->author = 11;
		$px->title =  'TitleBBB'; 
  		$px->save();
}public function chuongtrinhC(){
		$px = new PhieuXuat();
		$px->author = 11;
		$px->title =  'TitleCCC'; 
  		$px->save();
}

File View

<?php
/*** begin the session ***/
/*** create the form token ***/
$form_token = uniqid();
Session::put('form_token', $form_token); //$value = Session::get('key');
?>
    <form action="{{route('postTest')}}" method="post">
        <input type="hidden" name="form_token" value="<?php echo $form_token; ?>" />
        <div>
            <label for="name">Name</label>
            <input type="text" name="name" />
        <div>
        <div>
            <input type="submit" value="Add Name" />
        </div>@csrf()
    </form>

Với cách này khi mình cố tình click thật nhanh thì nó vấn insert dữ liệu nhiều lần. Đang bế tắc quá.

3 ANSWERS


Answered Jul 9th, 10:53 PM
+2

Dùng javascript disable button, form ... cách này không ổn vì nó chỉ giải quyết phía client sẽ ko triệt để được

Cách này trên thực tế lại khá hiệu quả, và được vài framework như mình biết là Rails (https://guides.rubyonrails.org/working_with_javascript_in_rails.html#automatic-disabling) dùng để ngăn người dùng double click.

Trong trường hợp cần ngăn chặn triệt để hơn ở phía backend, một cách đơn giản là chỉ cần thêm rate-limit để cùng một người dùng không thể submit quá nhiều lần trong khoảng thời gian ngắn. Giống như cách đa số các mã nguồn diễn đàn dùng, mỗi lần người dùng đăng bài/lập thread mà bài đăng gần nhất của họ đăng cách đây không lâu thì trả về thông báo lỗi.

Share
Answered Jul 10th, 3:59 AM
+2

Thực ra cái này phụ thuộc vào người dùng submit form nhiều lần vô tình hay cố tình. Và việc họ click nhiều lần hay không bản chất vẫn là việc gửi - nhận dữ liệu giữa client và server thông qua giao thức HTTP. Bạn có thể hạn chế người dùng bằng cách disable các button, nhưng còn việc họ dùng tool cố tình call các đầu api để insert nhiều dữ liệu vào database của mình thì sao 😂😂

Với user vô tình submit form thì bạn có thể sử dụng cách như bạn đã nói ở đầu bài, với một người non-tech thì họ cũng không có nhiều kiến thức để có thể sửa các element hay F12 chỉnh sửa các attribute. Nên mình nghĩ cách bên dưới là hợp lí.

Dùng javascript disable button, form ... cách này không ổn vì nó chỉ giải quyết phía client sẽ ko triệt để được

Với user cố tình phá hoại hệ thống thì họ có rất nhiều cách để insert nhiều bản ghi vào trong hệ thống của mình nếu như bạn không validate và có những cơ chế limit request hợp lí. Mình thấy có một số cách cơ bản sau bạn có thể tránh được việc này.

  1. Validate đầu vào chặt chẽ, ví dụ như bạn có một cái form register thông tin user, đảm bảo rằng ở tầng application(cụ thể là Laravel sử dụng form request để validate thông tin email là unique). Ngoài ra bạn còn có thể validate input thông qua việc looking row, hay là đánh các trường trong database là unique để đảm bảo việc dữ liệu không bị duplicate trong một số trường hợp.

  2. Limit request gửi lên server. Ví dụ như 1 phút với một phiên đăng nhập của người dùng chỉ được phép request tối đa 60 request chẳng hạn.

    Ưu điểm là setting rất dễ, cả ở tầng server và application, ví dụ như Laravel đã config sẵn cho chúng ta trong app/Http/Kernel.php

    Nhược điểm là họ có thể fake IP để loại bỏ việc limit request.


        'api' => [
            'throttle:60,1',
            'bindings',
        ],
  1. Sử dụng capcha, đối với mỗi form request mà hay bị tấn công, hãy sử dụng capcha để đảm bảo rằng kẻ phá hoại không thể cùng lúc tiến hành call nhiều request lên server.

    Ưu điểm của phương pháp này là có thể giải quyết được bài toán fake IP phía trên

    Nhược điểm là đem lại phiền toán cho người dùng bình thường, nhập capcha everywhere. Và việc triển khai cũng mất nhiều thời gian

  2. Sử dụng một số tool monitoring hệ thống, kịp thời phát hiện ra các IP khả nghi, phá hoại hệ thống để block hoặc đưa ra các phương pháp hạn chế người dùng hợp lí

Ngoài ra còn rất nhiều phương pháp nữa nhưng hi vọng các gợi ý trên đây có thể giúp đỡ được bạn

Share
Avatar TinhTN @tinhtn89
Jul 11th, 7:06 AM

Cảm ơn bạn đã phản hồi rất dài, rất có tâm luôn. Mình đang cần phải chống lại sự phá hoại nên các cách sử dụng phía client như jquery disable nút submit gần như ko dùng được. Cách giải quyết limit resquest thì là ok nhất nhưng vẫn ko hiểu sao nó lại không hoạt động. Mình đã làm thử 1 form submit bình thường insert dữ liệu vào db sử dụng session bên trên mình click thật nhanh 2 phát liền nó vẫn insert.

0
| Reply
Share
Avatar Quiet @simple1805
Jul 11th, 7:31 AM

@tinhtn89 Thế chỗ submit kia bạn sửa lại type bằng button đi, sau đó sử dụng Jquery để submit form, mình nghĩ lúc đó có thể xử lí được việc disbale button.

https://stackoverflow.com/questions/1200266/submit-a-form-using-jquery

0
| Reply
Share
Answered Jul 9th, 6:26 PM
0

Bạn nên set thêm trường timestamp cho mỗi insert record, rồi lấy timestamp vừa submit so sánh với timestamp ở record mới nhất, vd là một phút thì time ở submit trừ đi time ở record phải lớn hơn 1p rồi mới query insert... nếu sợ ảnh hưởng đến các client submit khác thì bạn nên fillter dữ liệu theo trường unique nữa nha.

Share
Avatar Noodle Wooden @noodle_wooden
Jul 30th, 4:29 AM
  • Cách làm disable ở web là đúng rồi.
  • Còn về BE: có thể tạo 1 queue để xử lý tuần tự / đồng thời theo một limit nhất định hoặc limit by id từ client gửi lên trong khoảng thời gian cho phép.
0
| Reply
Share
Viblo
Let's register a Viblo Account to get more interesting posts.