网站经常被机器人注册收到垃圾邮件,心情很糟糕。为了防止这类事件的发生,心血来潮,自己查找资料开发了验证码。下面是开发验证码一些感想。
验证码插件基本的思路就是:给用户一张带有数字的图片,然后在数据库里有这张图片内容的记录。只要将用户输入的内容同数据库的内容对比就可以判断是否输入正确的验证码了。
在joomla官网找了一些资料,不过很遗憾,关于验证码的插件的介绍,基本没有。只是简单的介绍了验证码响应的3个事件:
onInit 事件
onDisplay 事件
onCheckAnswer 事件
通过这3个事件大致可以猜想验证码插件的工作流程了。可能是在onDisplay事件中显示自定义的验证码的内容。在onCheckAnswer中判断用户的输入。
下一步具体就是研究一下系统自带的一个验证码插件的实现。(PHP编程有一个好处就是你可以随意的看到别名的源代码,而c++编程则没有那么好运气)
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 13 |
<?php /** * @package Joomla.Plugin * @subpackage Captcha * * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */
defined('_JEXEC') or die;
jimport('joomla.environment.browser');
/** * Recaptcha Plugin. * Based on the oficial recaptcha library( http://recaptcha.net/plugins/php/ ) * * @package Joomla.Plugin * @subpackage Captcha * @since 2.5 */ class plgCaptchaRecaptcha extends JPlugin { const RECAPTCHA_API_SERVER = "http://api.recaptcha.net"; const RECAPTCHA_API_SECURE_SERVER = "https://www.google.com/recaptcha/api"; const RECAPTCHA_VERIFY_SERVER = "api-verify.recaptcha.net";
public function __construct($subject, $config) { parent::__construct($subject, $config); $this->loadLanguage(); }
/** * Initialise the captcha * * @param string $id The id of the field. * * @return Boolean True on success, false otherwise * * @since 2.5 */ public function onInit($id) { // Initialise variables $lang = $this->_getLanguage(); $pubkey = $this->params->get('public_key', ''); $theme = $this->params->get('theme', 'clean');
if ($pubkey == null || $pubkey == '') { throw new Exception(JText::_('PLG_RECAPTCHA_ERROR_NO_PUBLIC_KEY')); }
$server = self::RECAPTCHA_API_SERVER; if (JBrowser::getInstance()->isSSLConnection()) { $server = self::RECAPTCHA_API_SECURE_SERVER; }
JHtml::_('script', $server.'/js/recaptcha_ajax.js'); $document = JFactory::getDocument(); $document->addScriptDeclaration('window.addEvent(\'domready\', function() { Recaptcha.create("'.$pubkey.'", "dynamic_recaptcha_1", {theme: "'.$theme.'",'.$lang.'tabindex: 0});});' );
return true; }
/** * Gets the challenge HTML * * @return string The HTML to be embedded in the form. * * @since 2.5 */ public function onDisplay($name, $id, $class) { return '<div id="dynamic_recaptcha_1"></div>'; }
/** * Calls an HTTP POST function to verify if the user's guess was correct * * @return True if the answer is correct, false otherwise * * @since 2.5 */ public function onCheckAnswer($code) { // Initialise variables $privatekey = $this->params->get('private_key'); $remoteip = JRequest::getVar('REMOTE_ADDR', '', 'SERVER'); $challenge = JRequest::getString('recaptcha_challenge_field', ''); $response = JRequest::getString('recaptcha_response_field', '');;
// Check for Private Key if (empty($privatekey)) { $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_NO_PRIVATE_KEY')); return false; }
// Check for IP if (empty($remoteip)) { $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_NO_IP')); return false; }
// Discard spam submissions if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_EMPTY_SOLUTION')); return false; }
$response = $this->_recaptcha_http_post(self::RECAPTCHA_VERIFY_SERVER, "/verify", array( 'privatekey' => $privatekey, 'remoteip' => $remoteip, 'challenge' => $challenge, 'response' => $response ) );
$answers = explode("\n", $response[1]);
if (trim($answers[0]) == 'true') { return true; } else { //@todo use exceptions here $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_'.strtoupper(str_replace('-', '_', $answers[1])))); return false; } }
/** * Encodes the given data into a query string format. * * @param string $data Array of string elements to be encoded * * @return string Encoded request * * @since 2.5 */ |
和一般的内容插件没有什么区别:
1、让我们自定的插件派生自JPlugin这个基类
2、构造函数的代码都是通用的,没有什么好介绍的。
3、在onInit()事件中,接受一个子徒的参数,表示字段的id.成功返回true,失败返回false.整个过程思路比较简单。获得后台的参数公共密钥,私有密钥,还有风格设定。然后就是在页面中引人ajax js代码,给ajax代码传递必要的参数。
4、onDisplay事件接受3个参数。一个是$name ,$id ,$class.具体什么意思还没研究。但本函数相当的简洁。只是简单的返回一个div块。应该是用来在表单中防止验证码图片的。
5、onCheckAnswer事件就是用来校验验证码的正确性的,在上面的代码中,调用http_post到服务器,以便校验杨验证码是否正确。
现在基本上可以开始写代码了。
基本的插件代码在这里就不啰嗦了。让我很意外的是:似乎系统并不是先执行onDisplay事件而是先执行onCheckAnswer事件。这点非常的奇怪。
完成验证码的开发,如果哪位朋友有需要,可以去ZMAX官网下载。更多joomla开发经验详谈咨询ZMAX团队。