10/10/2018, 11:11

Chống flood hiệu quả khi sử dụng ajax

Ví dụ trong trường hợp đăng ký thành viên.
Mình có trang index.php cho phép đăng ký thành viên.
Quá trình xử lý thông tin sẽ qua javascript và truyền dữ liệu đến file post.php bằng ajax (file post.php sẽ add thông tin vào database).
Ở đây mình nghĩ đến các giải pháp:
+ đặt captcha (hơi bất tiện)
+ set session timeout
+ dùng define (ko có hiệu quả khi mà file post.php được gọi qua ajax).

Chủ yếu ở đây mình muốn hạn chế người dùng truyền dữ liệu trực tiếp đến file post.php bằng form html mà họ tạo thôi. Mong các bạn đề xuất giải pháp.
vzic viết 13:15 ngày 10/10/2018
AJAX thì họ vẫn truyền được như thường thôi bạn. Cứ captcha đi. không bất tiện đâu. Bạn cứ tạo ra ảnh 1 dãy số đơn giản thì cũng nhanh thôi. . Cốt lõi captcha là để chống truy cập tự động. dãy số càng khó đoán thì khó vượt qua.
trunghieuhf viết 13:27 ngày 10/10/2018
bạn nào biết các open source họ dùng cách nào không, ví dụ ngay như post bài trong ddth.com (vBulletin)
VnVision viết 13:12 ngày 10/10/2018
vbb đâu phải open source

để chống flood do thành viên đã đăng ký thì khi họ post 1 bài, mốc thời gian (timestamp) của bài viết này sẽ được lưu lại trong csdl. Khi họ post 1 bài nữa, trc khi cho đăng script sẽ kiểm tra xem khoảng cách thời gian giữa 2 bài viết đã đủ dài chưa (bằng cách so sánh giữa mốc thời gian hiện tại & mốc thời gian của bài viết cuối của họ). Nếu đủ dài rồi mới cho đăng bài.

ko thể áp dụng cách này cho thành viên chưa đăng ký, vì không có bất kỳ cách nào chắc chắn để hạn chế một bot post bài ngoài việc yêu cầu nó xác nhận rằng nó là người chứ ko phải máy. Chẳng hạn có thể theo dõi các mốc thời gian post bài của 1 thành viên chưa đăng ký qua IP của họ để áp dụng giải pháp hạn chế như trên, nhưng bot có thể đổi IP để post bài.

captcha có 3 yếu tố quan trọng:
- dãy số phải đủ dài (tối thiểu nên để 4 ký tự) để bot ko thể brute force đc hoặc thời gian để brute force thành công 1 mã sẽ rất lâu (do cả network). Đúng ra cũng ko gọi là brute force đc vì khi bot nhập sai 1 captcha thì 1 captcha mới nên được sinh ra - sẽ tránh đc việc bot thử 1 dãy các ký tự có thể xuất hiện trong captcha để tìm ra kết hợp đúng.
- dãy số không được sử dụng những cách viết thông thường, dễ đọc (phải làm chúng uốn éo, thêm màu nền lòe loẹt cho khó nhìn...), và đặc biệt các ký tự ko đc theo 1 pattern nhất định (chẳng hạn chữ số 1 thì lúc phải đổ về bên phải, lúc phải đổ về bên trái..). Điều này nhằm tránh các phần mềm nhận dạng ký tự (OCR) đọc đc captcha
- dãy số captcha ko đc xuất hiện trên trang web ở bất cứ đâu (url hay nội dung html). Ngày trc tôi đã gặp trường hợp khi sửa code ng khác họ để nội dung captcha vào một hidden input field, để khi ng dùng gửi form thì so sánh captcha họ nhập với giá trị của hidden input đó).

nếu ko muốn dùng captcha có thể đặt câu hỏi ngẫu nhiên và yêu cầu ng dùng trả lời với đáp án nhất định. Chú ý: số lượng câu hỏi phải rất nhiều để tránh bot đoán mò ra đáp án (nếu số câu hỏi ít thì cũng giống như captcha có ít ký tự)
trunghieuhf viết 13:11 ngày 10/10/2018
Vậy nếu dùng cách chặn post trực tiếp từ html thì sao.
Ví dụ như tạo form html và gửi trực tiếp đến link: http://www.ddth.com/newreply.php?do=...y&t=553542 thì bị chặn lại.
VnVision viết 13:16 ngày 10/10/2018
Được gửi bởi trunghieuhf
Vậy nếu dùng cách chặn post trực tiếp từ html thì sao.
Ví dụ như tạo form html và gửi trực tiếp đến link: http://www.ddth.com/newreply.php?do=...y&t=553542 thì bị chặn lại.
Việc gửi form bằng cách nào lại là vấn đề khác ko ăn nhập gì với việc chặn flood. Bạn có thể gửi form tới 1 script (newreply.php) bằng javascript (ajax), submit form trên 1 trang html (nằm trên cùng website với script đó hoặc trên trang web khác), hoặc tự viết một chương trình submit form tới script đó. Nhưng nếu bạn theo dõi người dùng (đối với thành viên đã đăng ký) hoặc bắt họ xác nhận captcha (đối với guest) thì họ submit form theo cách nào cũng ko thể flood được.

Còn việc bạn hỏi chỉ đơn giản là làm sao phân biệt giữa 1 POST request gửi bởi javascript (ajax) & 1 request gửi bởi 1 html form. Google $_SERVER['HTTP_X_REQUESTED_WITH'] để tìm hiểu thêm. Tuy nhiên để chắc chắn hơn, vì ko phải javascript framework nào cũng gửi "X-Requested-With" header trong các ajax request của mình, bạn có thể thêm vào các ajax request một biến để php script có thể phân biệt giữa request = ajax & request thông thường. vd: http://www.ddth.com/newreply.php?do=...y&t=553542&ajax=1
trunghieuhf viết 13:19 ngày 10/10/2018
ý mình là ở đây không cho phép thực thi file post.php từ ngoài server ý.
Thường là dùng define tại index.php rồi check defined tại post.php, nhưng ở đây gọi post.php qua ajax nên ko check được defined.
Dùng $_SERVER['HTTP_X_REQUESTED_WITH']so sánh với 'XMLHttpRequest' thì có vẻ ok, nhưng mình chưa hiểu là trong trường hợp hợp nào thì sẽ không đúng.
Bạn có nói "Tuy nhiên để chắc chắn hơn, vì ko phải javascript framework nào cũng gửi "X-Requested-With" header trong các ajax request của mình, bạn có thể thêm vào các ajax request một biến để php script có thể phân biệt giữa request = ajax & request thông thường", mình không hiểu lắm, vì truy vấn của mình là qua ajax rồi mà. Mong giải thích thêm.
VnVision viết 13:16 ngày 10/10/2018
Được gửi bởi trunghieuhf
ý mình là ở đây không cho phép thực thi file post.php từ ngoài server ý.
Thường là dùng define tại index.php rồi check defined tại post.php, nhưng ở đây gọi post.php qua ajax nên ko check được defined.
HTML form thông thường bạn submit tới file nào thì form gửi = ajax cũng nên submit tới file đó. Nếu file index.php được dùng để xử lý form thông thường thì bạn cũng dùng chính nó để xử lý form gửi = ajax.

Được gửi bởi trunghieuhf
Dùng $_SERVER['HTTP_X_REQUESTED_WITH']so sánh với 'XMLHttpRequest' thì có vẻ ok, nhưng mình chưa hiểu là trong trường hợp hợp nào thì sẽ không đúng.
Chẳng hạn khi dùng các hàm gửi ajax request của jquery framework thì nó sẽ gửi kèm theo X-Requested-With header. Nhưng nếu bạn tự viết hàm gửi ajax, có thể bạn không cho nó gửi X-Requested-With header.

Được gửi bởi trunghieuhf
Bạn có nói "Tuy nhiên để chắc chắn hơn, vì ko phải javascript framework nào cũng gửi "X-Requested-With" header trong các ajax request của mình, bạn có thể thêm vào các ajax request một biến để php script có thể phân biệt giữa request = ajax & request thông thường", mình không hiểu lắm, vì truy vấn của mình là qua ajax rồi mà. Mong giải thích thêm.
Chẳng hạn trong file post.php bạn sẽ check xem request đc gửi bởi ajax hay thao tác thông thường của ng dùng như sau:
Code:
<?php
$is_ajax_request = isset($_GET['ajax']) ? true : false;
// $is_ajax_request có giá trị true nếu là request bởi ajax, false nếu ko phải. Dựa vào biến này để xử lý tiếp...
chesterben viết 13:15 ngày 10/10/2018
Hãy học cách làm của Google. Như form đăng nhập của Google Account, nếu bạn đăng nhập sai n lần thì sẽ xuất hiện captcha. Captcha thì có thể dùng reCaptcha cũng của Google luôn nên không sợ bị spam hệ thống. Chúc may mắn
trunghieuhf viết 13:17 ngày 10/10/2018
Vậy nếu 1 user tạo file index.php ở ngoài server, và truyền biến qua ajax vào file post.php ở trong server thì kết quả sẽ ra sao. Và lúc này thêm ajax=1 để check = php cũng vô nghĩa.
Giải pháp chống flood ở đây mình muốn nhắc đến chính là chặn không cho gửi dữ liệu từ 1 form ngoài server ý, còn trong server thì mình có thể kiểm soát đc.
Bài liên quan
0