How to validate Google reCAPTCHA v2 in django
Here is a simple example to verify Google reCAPTCHA v2 within Django view using requests
library (http://docs.python-requests.org/en/latest/):
import requests
from django.conf import settings
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
def grecaptcha_verify(request):
if request.method == 'POST':
response = {}
data = request.POST
captcha_rs = data.get('g-recaptcha-response')
url = "https://www.google.com/recaptcha/api/siteverify"
params = {
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': captcha_rs,
'remoteip': get_client_ip(request)
}
verify_rs = requests.get(url, params=params, verify=True)
verify_rs = verify_rs.json()
response["status"] = verify_rs.get("success", False)
response['message'] = verify_rs.get('error-codes', None) or "Unspecified error."
return HttpResponse(response)
There is a third-party Django app to implement the new reCAPTCHA v2 here:
https://github.com/ImaginaryLandscape/django-nocaptcha-recaptcha
After installing it, add the following lines to the following files:
# settings.py
NORECAPTCHA_SITE_KEY = <the Google provided site_key>
NORECAPTCHA_SECRET_KEY = <the Google provided secret_key>
INSTALLED_APPS = (
....
'nocaptcha_recaptcha'
)
#forms.py
from nocaptcha_recaptcha.fields import NoReCaptchaField
class YourForm(forms.Form):
.....
captcha = NoReCaptchaField()
# In your template, add the following script tag:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Google has changed the API around, we need to use a POST request now. Here a re-usable solution in case you need to do the validation in more than one django view:
utils.py
# django imports
from django.conf import settings
from django.views.generic.base import View
from django.http import HttpResponseForbidden
# 3rd-party imports
import requests
from ipware import get_client_ip
def is_recaptcha_valid(request):
"""
Verify if the response for the Google recaptcha is valid.
"""
return requests.post(
settings.GOOGLE_VERIFY_RECAPTCHA_URL,
data={
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': request.POST.get('g-recaptcha-response'),
'remoteip': get_client_ip(request)
},
verify=True
).json().get("success", False)
def human_required(view_func):
"""
This decorator is aimed to verify Google recaptcha in the backend side.
"""
def wrapped(request, *args, **kwargs):
if is_recaptcha_valid(request):
return view_func(request, *args, **kwargs)
else:
return HttpResponseForbidden()
return wrapped
then:
views.py
from utils import human_required
class MyView(View):
@human_required
def post(request, *args, **args):
pass
Note we are using django-ipware in this solution to get the ip address, but this is up to you. Also, don't forget to add GOOGLE_VERIFY_RECAPTCHA_URL
and RECAPTCHA_SECRET_KEY
to the django settings file!