I have been trying to use the Google reCAPTCHA on a website that I've been making. The captcha loads on the webpage but I've been unable to validate it using several methods. I've tried the recaptcha validation using the method given at
How to use Python plugin reCaptcha client for validation? but I think it's outdated as it no longer works and it is referring to challenges whereas the one I'm trying to use is the new 'checkbox' reCAPTCHA v2 by Google or maybe I need to make changes in my settings after installing recaptcha-client or django-recaptcha.
Please help!
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>
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)
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!