Membuat Captcha Matematika Sederhana dengan Python

Singkatnya, CAPTCHA adalah uji challenge-response untuk memastikan bahwa yang dapat mengakses sebuah sistem hanyalah manusia, bukan bot. CAPTCHA sendiri adalah singkatan dari Completely Automated Public Turing test to tell Computers and Humans Apart. Contoh implementasi yang paling mudah dijumpai adalah submisi form html.

Sebagai contoh, laman contact me pada blog ini untuk sementara menggunakan operasi matematika penjumlahan. Contoh lainnya yaitu laman web forlap ristekdikti untuk mencari data mahasiswa di Indonesia.

Contoh Implementasi Menggunakan Python (Django Framework)

Pada View, buat dua operan menggunakan fungsi randint. Agar nilainya tidak terlalu besar, saya menggunakan parameter (1, 50) untuk menghasilkan bilangan bulat antara 1 sampai 50. Lewatkan dua variabel pengaman itu ke template (misalnya menggunakan render). Pada contoh di bawah, variabel itu bernama captcha1 dan captcha2.

from random import randint
context = {
    'captcha1': randint(1, 50),
    'captcha2': randint(1, 50),
}
return render(request, 'blog/contact_me.html', context)

Pada form html, tambahkan dua input tersembunyi di dalam form, dan juga input untuk menerima hasil kalkulasi dari user.

<label for="captcha-id">Hitung {{captcha1}} + {{captcha2}} =</label>
<input name="captcha-user-response" type="number" class="form-control" id="captcha-id" required>
<input name="c1" type="hidden" value="{{captcha1}}">
<input name="c2" type="hidden" value="{{captcha2}}">

Ketika user mensubmit form tersebut, periksa hasil kalkulasi.

if request.method == 'POST':
    # Validasi hasil kalkulasi
    c1 = int(request.POST.get('c1'))
    c2 = int(request.POST.get('c2'))
    captcha_user_response = int(request.POST.get('captcha-user-response'))
    if captcha_user_response == c1 + c2:
        messages.info(request, 'Operasi sukses.')
        # Tambahkan kode program lainnya
    else:
        messages.error(request, "Gagal.")

Membuat Pilihan Operasi: Penjumlahan dan Pengurangan

Pada contoh di atas, operasi yang digunakan untuk menguji user adalah penjumlahan. Kita bisa membuat dua alternatif acak yaitu penjumlahan dan pengurangan menggunakan session dan fungsi randint.

Pada View:

from random import randint
captcha1 = randint(1, 50)
captcha2 = randint(1, 50)
operation = randint(1, 2)
if operation == 1:
    challenge = '%s + %s' % (captcha1, captcha2)
    request.session['answer'] = captcha1 + captcha2
else:
    challenge = '%s - %s' % (captcha1, captcha2)
    request.session['answer'] = captcha1 - captcha2
    
context = {
    'challenge': challenge,
}
return render(request, 'contact/contact.html', context)

Pada form html:

<label for="captcha-id">Hitung {{challenge}} =</label>
<input name="captcha-user-response" type="number" class="form-control" id="captcha-id" >

Pada View (POST) untuk memeriksa hasil:

if request.method == 'POST':
    # Validasi captcha
    captcha_user_response = int(request.POST.get('captcha-user-response'))
    if captcha_user_response == request.session.get('answer'):
        # Sukses
    else:
        # Gagal

Kesimpulan

Implementasi yang dijelaskan di sini hanyalah contoh sederhana dan memiliki beberapa kelemahan. Misalnya, tidak ada timeout untuk setiap challenge yang dihasilkan.

Agar lebih aman lagi, kita bisa menggunakan uji gambar atau suara, seperti digunakan oleh banyak sistem captcha yang populer, misalnya reCAPTCHA dan Invisible reCAPTCHA milik Google.