Skip to content

Commit 7ba2a9b

Browse files
authored
captcha for filter page (#81)
1 parent d0e2475 commit 7ba2a9b

4 files changed

Lines changed: 69 additions & 2 deletions

File tree

forums/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@
276276
'django.contrib.sessions.middleware.SessionMiddleware',
277277
'django.middleware.common.CommonMiddleware',
278278
'django.middleware.csrf.CsrfViewMiddleware',
279+
'website.middleware.FilterCaptchaGateMiddleware',
279280
'django.contrib.auth.middleware.AuthenticationMiddleware',
280281
'django.contrib.messages.middleware.MessageMiddleware',
281282
'django.middleware.clickjacking.XFrameOptionsMiddleware',
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Verifying browser...</title>
6+
<script src="https://www.google.com/recaptcha/api.js?render={{ site_key }}"></script>
7+
</head>
8+
<body>
9+
<p>Verifying your browser...</p>
10+
<form id="verify-form" method="post" action="{% url 'website:verify_filter_access' %}">
11+
{% csrf_token %}
12+
<input type="hidden" name="token" id="recaptcha_token">
13+
<input type="hidden" name="next" value="{{ next_url }}">
14+
</form>
15+
16+
<script>
17+
grecaptcha.ready(function() {
18+
grecaptcha.execute('{{ site_key }}', {action: 'filter_page'}).then(function(token) {
19+
document.getElementById('recaptcha_token').value = token;
20+
document.getElementById('verify-form').submit();
21+
});
22+
});
23+
</script>
24+
</body>
25+
26+
</html>
27+
</html>

website/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,7 @@
3838
url(r'^ajax-time-search/$', views.ajax_time_search, name='ajax_time_search'),
3939
url(r'^ajax-delete-question/$', views.ajax_delete_question, name='ajax_delete_question'),
4040
url(r'^ajax-hide-question/$', views.ajax_hide_question, name='ajax_hide_question'),
41+
42+
#captcha
43+
url(r'^verify-filter-access/$', views.verify_filter_access, name='verify_filter_access'),
4144
]

website/views.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import requests
33

44
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
5-
from django.shortcuts import render, get_object_or_404
5+
from django.shortcuts import render, get_object_or_404, redirect
66
from django.template.context_processors import csrf
77
from django.contrib.auth.decorators import login_required
88
from django.contrib import messages
@@ -166,7 +166,6 @@ def home(request):
166166
uids.add(q.last_post_by)
167167

168168
users = {u.id: u.username for u in User.objects.filter(id__in=uids)}
169-
170169
# Attach usernames to question objects so templates don't trigger queries
171170
for q in all_questions:
172171
q.cached_user = users.get(q.uid, "Unknown User")
@@ -1090,3 +1089,40 @@ def unanswered_notification(request):
10901089
if total_count:
10911090
forums_mail(to, subject, message)
10921091
return HttpResponse(message)
1092+
1093+
1094+
def verify_filter_access(request):
1095+
if request.method != 'POST':
1096+
return HttpResponseForbidden("Invalid request method")
1097+
1098+
token = request.POST.get('token', "").strip()
1099+
next_url = request.POST.get('next', "").strip()
1100+
1101+
if not token:
1102+
return HttpResponseForbidden("Missing captcha token")
1103+
1104+
try:
1105+
data = {'secret': settings.RECAPTCHA_SECRET_KEY, 'response': token}
1106+
resp = requests.post('https://www.google.com/recaptcha/api/siteverify',
1107+
data, timeout=5)
1108+
result = resp.json()
1109+
except Exception:
1110+
return HttpResponseForbidden("Captcha verification service unavailable")
1111+
1112+
success = result.get('success', False)
1113+
score = result.get('score', 0.0)
1114+
action = result.get('action', "")
1115+
1116+
1117+
# Tune score threshold as needed.
1118+
if not success:
1119+
return HttpResponseForbidden("Captcha verification failed")
1120+
if action != 'filter_page':
1121+
return HttpResponseForbidden("Invalid captcha action")
1122+
if score < 0.5:
1123+
return HttpResponseForbidden("Request looks suspicious")
1124+
1125+
request.session["filter_verified"] = True
1126+
# optionally, set filter_verified_at timestamp session for seperate filter_verify expiiry
1127+
1128+
return redirect(next_url)

0 commit comments

Comments
 (0)