使用Zope2验证reCaptcha2

时间:2019-02-12 22:26:59

标签: python python-2.7 recaptcha zope dtml

我使用Zope 2.13.29和Python 2.7.15,尝试使用从DTML文档调用的Python脚本来验证Google的reCaptcha2。 DTML文档包含表单,并且同一DTML文档使用dtml-if语句来确定用户单击提交后是否处理该表单。在dtml-if语句中包含一个dtml-in,该dtml-in调用python脚本以验证reCaptcha并返回成功值(True或False)。问题是我似乎无法获得成功的价值。

虽然我知道你们中的一些人可能倾向于谈论RestrictedPython以及我将如何无法导入供Zope使用的python模块,但是这部分已经处理完毕。一切正常,只是没有做我需要做的事。

这是显示联系表单的dtml-doc,并确定是否单击了提交,这反过来又调用了python脚本,以最终确定从reCaptcha返回的Google成功变量的值。

<dtml-if submit>

<dtml-with recaptcha-validate>

<dtml-if expr="'success' == True">

<dtml-sendmail mailhost="MailHost">
To: info@foo.com
From: &dtml.lower-emailaddr;
Subject: Web Request

&dtml-message;

Sincerely,

&dtml-realname;
&dtml-emailaddr;
&dtml-phone;
&dtml-location;

</dtml-sendmail>

<dtml-else>

<dtml-sendmail mailhost="MailHost">
To: info@foo.com
From: &dtml.lower-emailaddr;
Subject: SPAM: Web Request

&dtml-message;

Sincerely,

&dtml-realname;
&dtml-emailaddr;
&dtml-phone;
&dtml-location;

</dtml-sendmail>

</dtml-if>
</dtml-with>

<dtml-else submit>

<dtml-var "foo.sitefiles.doctype(_.None, _)">
<html>
<head>
<title>Contact Us</title>

<script src="https://www.foo.com/javascript/jquery/jquery-min.js" type="text/javascript"></script>
<script src="https://www.foo.com/javascript/parsley/parsley.min.js" type="text/javascript"></script>

<script src="https://www.foo.com/javascript/misc/placeholder.js" type="text/javascript"></script>

<script src="https://www.google.com/recaptcha/api.js"></script>

</head>

<body>

<form data-parsley-validate id="contact-form" method="post" action=<dtml-var URL0> novalidate="" parsley-validate="" parsley-focus="none" data-parsley-errors-messages-disabled data-parsley-excluded="input[name=g-recaptcha-response], input[id=recaptcha-token]">
<fieldset>
<label>NAME</label>
<input class="parsley-validated" type="text" name="realname" placeholder="Enter your name" value="" required="">
<label>E-MAIL</label>
<input class="parsley-validated" type="email" name="emailaddr" placeholder="Enter your e-mail" value="" required="" pattern="^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$">
<label>PHONE NUMBER</label>
<input class="parsley-validated" type="text" name="phone" placeholder="Enter your contact phone number" value="" required="" pattern="^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$">
<label>LOCATION</label>
<input class="parsley-validated" type="text" name="location" placeholder="Enter your city, state" value="">
<label>MESSAGE</label>
<textarea class="parsley-validated" name="message" placeholder="Enter your message here" value="" required="" rows="8"></textarea>
<input id="myField" data-parsley-errors-container="#errorContainer" data-parsley-required="true" value="" type="text" style="display:none;">
<div id="contactrecaptcha">
<div id="recaptchatoken" class="g-recaptcha" data-sitekey="XXXXXXXXXX" data-        callback="recaptchaCallback"></div>
</div>
<span id='errorContainer'></span>
</fieldset>
<input type="submit" name="submit" value="SUBMIT">
</form>

<script type="text/javascript">
$('#contact-form').parsley();
function recaptchaCallback() {
    document.getElementById('myField').value = 'nonEmpty';
}
</script>

</body>
</html>

</dtml-if>

这是python脚本(名为recaptcha-validate):

import urllib
import urllib2
import json

REQUEST = container.REQUEST

URIReCaptcha = 'https://www.google.com/recaptcha/api/siteverify'
secret = 'XXXXXXXXXXXXXXXXXXX'
recaptcha_response = context.REQUEST['g-recaptcha-response']
remoteip = REQUEST.HTTP_X_FORWARDED_FOR

params = urllib.urlencode({
'secret': secret,
'response': recaptcha_response,
'remoteip': remoteip,
})

#print params
from urllib2 import urlopen
req = urllib2.Request(URIReCaptcha, params)
response = urllib2.urlopen(req)
result = json.load(response)
success = result.get('success', None)
return{'success': success}

当通过“测试”选项卡从ZMI运行脚本时,我希望结果为假,我会回来

{'成功':错误}

但是,我似乎无法从DTML文档中调用成功变量。

应该提交表单,应该运行python脚本并验证Recaptcha,返回成功值(True / False),然后dtml-if应该决定如何继续处理表单。

2 个答案:

答案 0 :(得分:0)

我不确定,但是我认为您应该尝试创建dtml方法,而不是dtml-doc。

https://zope.readthedocs.io/en/latest/zope2book/DTML.html#formatting-and-displaying-sequences

您还应该考虑使用ZPT代替DTML。

看看第一个音符:https://zope.readthedocs.io/en/latest/zope2book/DTML.html#basic-dtml

答案 1 :(得分:0)

经过大量工作,并与许多不同的人交谈,Plone论坛上的一个非常友善的人向我展示了我做错了什么。我说的太难了,但是非常接近。

这是python脚本(名为recaptcha_validate):

import urllib
import urllib2
import json

REQUEST = container.REQUEST

URIReCaptcha = 'https://www.google.com/recaptcha/api/siteverify'
secret = 'XXXXXXXXXXX'
recaptcha_response = context.REQUEST['g-recaptcha-response']
remoteip = REQUEST.HTTP_X_FORWARDED_FOR

params = urllib.urlencode({
'secret': secret,
'response': recaptcha_response,
'remoteip': remoteip,
})

#print params
from urllib2 import urlopen
req = urllib2.Request(URIReCaptcha, params)
response = urllib2.urlopen(req)
result = json.load(response)
success = result.get('success', None)
return success

这是dtml-doc的顶部,用于检查是否单击了提交并选择了如何处理表单:

<dtml-if submit>

<dtml-if recaptcha_validate>

<dtml-sendmail mailhost="MailHost">
To: info@foo.com
From: &dtml.lower-emailaddr;
Subject: Web Request

&dtml-message;

Sincerely,

&dtml-realname;
&dtml-emailaddr;
&dtml-phone;
&dtml-location;

</dtml-sendmail>

<dtml-else>

<dtml-sendmail mailhost="MailHost">
To: info@foo.com
From: &dtml.lower-emailaddr;
Subject: SPAM: Web Request

&dtml-message;

Sincerely,

&dtml-realname;
&dtml-emailaddr;
&dtml-phone;
&dtml-location;

</dtml-sendmail>

</dtml-if>

做一个简单的

<dtml-if recaptcha_validate>

运行python脚本并检查结果是否为true。在这种情况下,不需要任何变量或表达式。真的就是这么简单。

注意:使用

<dtml-sendmail>

标签,并且只想更改主题,我尝试在主题:Web请求行中使用

<dtml-if recaptcha_validate>

声明。那行不通。您必须有两个完全分开的

<dtml-sendmail>

节,以使其正常工作。