Using Google reCAPTCHA in Django forms is one of the best way to prevent DOS attack in your Django application. Although you may deploy other measures like blocking user after 3 unsuccessful attempts or blocking the IP address but I think reCAPTCHA is one of the most widely used method to stop bots from attacking your login/sign-in page.
In this article we will see how to use Google reCAPTCHA in Django forms.
After registering, site key and secret key will be generated.
Add <div class="g-recaptcha" data-sitekey="XXeZ2XXAAXAAKrOXXXZ1fXDwXXX7xKgXXMAFYXX"></div>
inside your form.
<form action="{{url}}" method="post"> {% csrf_token %} <input type="email" placeholder="email"> <input type="password" placeholder="password"> <div class="g-recaptcha" data-sitekey="XXeZ2XXAAXAAKrOXXXZ1fXDwXXX7xKgXXMAFYXX"></div> <input type="submit" value="login"> </form>
Now inside ModelForm class of above form, use clean method to validate the reCAPTCHA.
def clean(self): ca = self.request.POST["g-recaptcha-response"] url = "https://www.google.com/recaptcha/api/siteverify" params = { 'secret': config.RECAPTCHA_SECRET_KEY, 'response': ca, 'remoteip': utility.get_client_ip(self.request) } verify_rs = requests.get(url, params=params, verify=True) verify_rs = verify_rs.json() status = verify_rs.get("success", False) if not status: raise forms.ValidationError( _('Captcha Validation Failed.'), code='invalid', )
I have stored the RECAPTCHA_SECRET_KEY
in a separate config file and imported the config file in ModelForm file.
It is always recommended to store all secret keys and credentials in separate config file and do not commit this file to version control system (git).
In the above code you can see we are fetching captcha value from request.POST
. To access the request
object in ModelForm, define below method in your ModelForm class.
def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) super(MyModelForm, self).__init__(*args, **kwargs)
Now when using this ModelForm class in your view code, use below code.
post_data = request.POST form = MyModelForm(post_data,request=request)
I have created a separate utility class to keep some utility functions there. get_client_ip
is one such function.
We need to import both, config and utility in this file.
Code to get client's IP address:
def get_client_ip(request): x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: ip = x_forwarded_for.split(',')[0] else: ip = request.META.get('REMOTE_ADDR') return ip
So in above code, we collect recaptch value from request and send it to Google along with client's IP address.
Google return the response which is converted to JSON object and verified if success is returned.
If validation fails, we raise form validation error.
Bonus:
Google reCAPTCHA: https://www.wired.com/2014/12/google-one-click-recaptcha/
Robot beating Google in 'I am not a robot' test: https://nakedsecurity.sophos.com/2017/01/31/im-not-a-robot-verification-test-beaten-by-a-robot/