在Marionette Itemview中渲染reCaptcha V2.0小部件

时间:2018-04-04 12:04:42

标签: javascript java recaptcha marionette captcha

这将是我提出问题并提出解决方案的帖子 由于遇到了一些麻烦并且经常环顾四周,我决定将其最终解决方案发布给其他任何人以从中获利。

问题: 如何渲染谷歌的reCaptcha v2.0小部件并在带有java后端的Marionettejs应用程序中进行验证。

1 个答案:

答案 0 :(得分:1)

在常见步骤和以下谷歌指南呈现重新验证后,我的验证码仍然无法渲染,所以这里是我的解决方案:

渲染验证码和包含脚本都是在itemview onRender函数中进行的:

    'text!login/templates/form.html',
    'app'
], function (app, Marionette, Backbone, _, $, Handlebars, FormTemplate) {
 return Marionette.ItemView.extend({

    template: Handlebars.compile(FormTemplate),

    ui: {
        form: '
    },

    events: {
        'submit @ui.form': 'onSubmit'
    },

    onRender: function() {
      this.loadCaptcha();
    },

    loadCaptcha: function() {
        var self = this;
        var getRecaptchaResponse = function(response) {
            self.captchaResponse = response;
        };

        window.renderCaptcha = function () {
            self.captchaWidgetId = grecaptcha.render('yourCaptchaDiv', {
                sitekey: 'YourSiteKey',
                callback: getRecaptchaResponse
            });
        };

        $.getScript('https://www.google.com/recaptcha/api.js?onload=renderCaptcha&render=explicit', function() {});
    },
...
}

我尝试了其他方法来加载脚本中的几个错误,比如在div之前加载的脚本,或者浏览器说de Dom已经完全加载但是onRender在之后被调用

我必须为要加载的captcha小部件包含一个div,这是在 form.html

<div id="reCaptcha" class="btn"></div>

这会渲染你的小部件,现在你需要验证它已被填充并且它是google的有效用户响应,为此我使用相同的模块并使用下一个函数:

onSubmit: function (e) {
//only act if the captcha has been filled - This could be easily erased from a browser, but a back end verification takes place too
            if (grecaptcha.getResponse() !== "") {
                e.preventDefault();
                var _view = this;
                this.blockForm();
                $.ajax({
                    url: 'yourLoginService',
                    type: 'POST',
                    data: {
                        userLogin: this.ui.user.val(),
                        userPassword: this.ui.password.val(),
                        //get the captcha response
                        captchaResponse: grecaptcha.getResponse()
                    }

                }).done(function (data) {
                    app.router.navigate('', {trigger: true});
                    _view.destroy();
                }).fail(function (jqXHR, textStatus, errorThrown) {
                  // your fail handling
                });
            }
        },

然后是时候使用谷歌提供的密钥验证您的验证码服务器端(注意这是一个Java6应用程序,因此繁琐的异常处理):

//some other imports ignored
import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;

class Captcha {

    private static final String CAPTCHA_SECRET_KEY = "YourSecretKey";
    private static final Logger LOGGER = Logger.getLogger(Captcha.class);

    static boolean isCaptchaValid(String response) {
        try {
            String url = "https://www.google.com/recaptcha/api/siteverify?"
                    + "secret=" + CAPTCHA_SECRET_KEY
                    + "&response=" + response;

            InputStream res = new URL(url).openStream();
            JSONObject json = new JSONObject(getJsonResponse(res));
            res.close();    
            return json.getBoolean("success");
        } catch (JSONException e) {
            LOGGER.error("Can not parse captcha response Json: " + e);
            return false;
        } catch (MalformedURLException e) {
            LOGGER.error("Malformed URL: " + e);
            return false;
        } catch (IOException e) {
            LOGGER.error("Error reading response from captcha verification response: " + e);
            return false;
        }
    }

    private static String getJsonResponse(InputStream res) throws IOException {
        BufferedReader rd = new BufferedReader(new InputStreamReader(res, Charset.forName("UTF-8")));
            /*TODO in java 8+ use this and avoid using the external library
                return rd.lines().collect(Collectors.joining());
             */
        return IOUtils.toString(rd);
    }
}