Joomla验证码的开发

原创
2015/11/12 11:00
阅读数 88

网站经常被机器人注册收到垃圾邮件,心情很糟糕。为了防止这类事件的发生,心血来潮,自己查找资料开发了验证码。下面是开发验证码一些感想。

验证码插件基本的思路就是:给用户一张带有数字的图片,然后在数据库里有这张图片内容的记录。只要将用户输入的内容同数据库的内容对比就可以判断是否输入正确的验证码了。

在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团队。

 


展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部