简体   繁体   English

带有苗条的谷歌验证码

[英]Google captcha with svelte

So I had an issue with svelte and google Recaptcha API.所以我遇到了 svelte 和 google Recaptcha API 的问题。

My main HTML file我的主要 HTML 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset='utf-8'>
    <meta name='viewport' content='width=device-width,initial-scale=1'>

    <title>Svelte app</title>

    <link rel='icon' type='image/png' href='/favicon.png'>
    <link rel='stylesheet' href='/global.css'>
    <link rel='stylesheet' href='/build/bundle.css'>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bitter:400,700">
    <link rel="stylesheet" href="/css/styles.min.css">

    <script defer src='/build/bundle.js'></script>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
</head>

<body>
</body>
</html>

My main.svelte我的 main.svelte

<script>
  import swal from "sweetalert";

  function verifyUser() {
    swal({
      title: "Please wait a minute!",
      text: "Do not close or exit this tab, we are currently verifying you...",
      icon: "info",
      backdrop: `rgba(0,0,0,1)`,
      showConfirmButton: false,
      allowOutsideClick: false,
      allowEscapeKey: false
    });
  }
</script>

<div>
  <div class="header-dark">
    <nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search">
      <div class="container">
        <a class="navbar-brand" href="/">QSP Human Verification Module</a>
        <button class="navbar-toggler" data-toggle="collapse">
          <span class="sr-only">Toggle navigation</span>
          <span class="navbar-toggler-icon" />
        </button>
      </div>
    </nav>
    <div class="container hero">
      <div class="row">
        <div class="col-md-8 offset-md-2">
          <h1 class="text-center">
            Please complete the Captcha challenge to continue to the server.
          </h1>

          <form action="" method="post">

            <div
              class="g-recaptcha"
              data-sitekey="key"
              data-callback={verifyUser}
             />
          </form>

        </div>
      </div>
    </div>
  </div>
</div>

Problem is that function just becomes string of itself and can't be executed using just "verifyUser" or verifyUser() returns ReCAPTCHA couldn't find user-provided function: verifyUser`问题是函数只是变成了自己的字符串,不能只使用"verifyUser" or verifyUser() 执行returns ReCAPTCHA 找不到用户提供的函数:verifyUser`

using {verifyUser} becomes string (for more https://prnt.sc/qhyc2w )使用{verifyUser}成为字符串(更多https://prnt.sc/qhyc2w

executing like that returns:像这样执行返回:

ReCAPTCHA couldn't find user-provided function: function verifyUser() {
        swal({
            title: "Please wait a minute!",
            text: "Do not close or exit this tab, we are currently verifying you...",
            icon: "info",
            backdrop: `rgba(0,0,0,1)`,
            showConfirmButton: false,
            allowOutsideClick: false,
            allowEscapeKey: false
        });
    }

rollup config汇总配置

import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';

const production = !process.env.ROLLUP_WATCH;

export default {
    input: 'src/main.js',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/build/bundle.js'
    },
    plugins: [
        svelte({
            // enable run-time checks when not in production
            dev: !production,
            // we'll extract any component CSS out into
            // a separate file — better for performance
            css: css => {
                css.write('public/build/bundle.css');
            }
        }),

        // If you have external dependencies installed from
        // npm, you'll most likely need these plugins. In
        // some cases you'll need additional configuration —
        // consult the documentation for details:
        // https://github.com/rollup/plugins/tree/master/packages/commonjs
        resolve({
            browser: true,
            dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
        }),
        commonjs(),

        // In dev mode, call `npm run start` once
        // the bundle has been generated
        !production && serve(),

        // Watch the `public` directory and refresh the
        // browser on changes when not in production
        !production && livereload('public'),

        // If we're building for production (npm run build
        // instead of npm run dev), minify
        production && terser()
    ],
    watch: {
        clearScreen: false
    }
};

function serve() {
    let started = false;

    return {
        writeBundle() {
            if (!started) {
                started = true;

                require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
                    stdio: ['ignore', 'inherit', 'inherit'],
                    shell: true
                });
            }
        }
    };
}

Any how to properly pass the function?任何如何正确传递函数?

im Rour- the guy from discord. im Rour - 来自不和谐的家伙。 I want to share solution here for others.我想在这里为其他人分享解决方案。

<script>
import { onMount, onDestroy } from 'svelte';

function verifyUser() {/* your fun here */}

onMount(() => {
  window.verifyUser = verifyUser;
})

onDestroy(() => {
  window.verifyUser = null;
})
</script>
<!-- then pass the name of function 'verifyUser' just as string' -->
<div class="g-recaptcha" data-sitekey="key" data-callback="verifyUser" />

Thinking that data-callback is searching for name of global function, so we define verifyUser as global function in the browser by assign it to the window variable认为data-callback是搜索全局函数的名字,所以我们在浏览器中定义verifyUser为全局函数,将它赋值给window变量

You can try svelte-recaptcha-v2 package on npm for a more straight forward experience.您可以在 npm 上尝试svelte-recaptcha-v2包以获得更直接的体验。

Repository存储库

https://github.com/basaran/svelte-recaptcha-v2 https://github.com/basaran/svelte-recaptcha-v2

Demo演示

https://basaran.github.io/svelte-recaptcha-v2/ https://basaran.github.io/svelte-recaptcha-v2/

PS I'm the author of the package. PS我是包的作者。

If using TypeScript, you'll need to define your function for the Window interface.如果使用 TypeScript,则需要为 Window 接口定义函数。

global.d.ts global.d.ts

declare interface Window {
  onSubmit: (token) => void,
}

RecaptchaButton.svelte RecaptchaButton.svelte

<script lang="ts">
  import { createEventDispatcher, onMount, onDestroy } from 'svelte';
  import { variables } from '../../variables';

  const { recaptchaSiteKey } = variables;
  const dispatch = createEventDispatcher();
  type ButtonType = 'primary' | 'secondary';
  export let type: ButtonType = 'primary';

  function onSubmit(token) {
    dispatch('click', { token });
  }

  onMount(() => {
    window.onSubmit = onSubmit;
  });

  onDestroy(() => {
    window.onSubmit = null;
  });
</script>

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

<form on:submit|preventDefault={onSubmit}>
  <button
    class="g-recaptcha {type}"
    data-sitekey={recaptchaSiteKey}
    data-callback="onSubmit"
    type="submit"
  >
    Submit
  </button>
</form>

<style>
  button {
    ...
  }
  ...
</style>

ContactForm.svelte ContactForm.svelte

<script>
  function handleSubmit(event) {
    console.log(event.detail.token);
    return;
  }
</script>

<RecaptchaButton on:click={handleSubmit} type="primary">Submit</ButtonRecaptcha>

You should add an error handler to the Recaptcha button component if using something like the above, you can use the "data-error-callback" property on the buttton;如果使用类似上面的内容,您应该向 Recaptcha 按钮组件添加一个错误处理程序,您可以使用按钮上的“data-error-callback”属性; set up the Window interface, mount and destroy the same as "onSubmit" but with "onError".设置Window接口,挂载和销毁与“onSubmit”相同但带有“onError”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM