适用于网站和博客

为你的网站添加测验

选择一个题集,设置颜色和文字,然后把代码复制到你的页面中。每次访问都会出现 9 道不同的免费题目,每回答一题,马赛克就填满一块。

内容
外观
文字

预览

嵌入代码

将代码粘贴到页面中希望显示测验的位置。

须知

可选:通过你自己的域名嵌入

如果你不希望向第三方服务器发出任何请求,可以由你的 Web 服务器提供测验:它把 /qwissit/ 这样的路径转发给 Qwissit。这样访客的浏览器只与你的域名通信,Qwissit 只能看到你服务器的地址。上面的直接嵌入仍是简单的默认方式。

1. 配置 Web 服务器:把 /qwissit/ 转发到 https://www.qwissit.com/widget/v1/,不传递访客的 Cookie、IP 地址或其他信息。

nginx
location ^~ /qwissit/ {
    proxy_pass https://www.qwissit.com/widget/v1/;
    proxy_set_header Host www.qwissit.com;
    proxy_ssl_server_name on;
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Real-IP "";
    proxy_set_header Cookie "";
    proxy_set_header Referer "";
    proxy_set_header User-Agent "qwissit-proxy";
    proxy_hide_header Set-Cookie;
}
Apache (mod_proxy, mod_ssl, mod_headers)
SSLProxyEngine On
<Location "/qwissit/">
    ProxyPass "https://www.qwissit.com/widget/v1/"
    ProxyAddHeaders Off
    RequestHeader unset Cookie
    RequestHeader unset Referer
    RequestHeader set User-Agent "qwissit-proxy"
    Header unset Set-Cookie
</Location>
Caddy
handle_path /qwissit/* {
    rewrite * /widget/v1{path}?{query}
    reverse_proxy https://www.qwissit.com {
        header_up Host {upstream_hostport}
        header_up -X-Forwarded-For
        header_up -Cookie
        header_up -Referer
        header_up User-Agent qwissit-proxy
        header_down -Set-Cookie
    }
}
PHP (Shared Hosting)

无法修改服务器配置(共享主机)?下载 PHP 文件,以 qwissit-proxy.php 保存到网站目录,并把 /qwissit-proxy.php/qwissit-widget.js 用作脚本地址。它只转发小组件的文件。

下载 qwissit-proxy.php

2. 替换上面代码中的脚本地址:

<script src="/qwissit/qwissit-widget.js" async></script>

3. 自检:用你的域名发起此请求,必须返回 200 和 content-type: text/javascript。返回 404 时请查看“无法正常工作时”中的各项;返回 HTML 页面说明请求被你的 CMS 接管了。

curl -I https://example.org/qwissit/qwissit-widget.js

然后在浏览器中用开发者工具(F12)打开“网络”标签:不应出现任何发往 www.qwissit.com 的请求。

无法正常工作时
  • nginx 返回 404:像 location ~* \.(js|css)$ 这样的静态文件规则优先于普通的前缀规则,于是 nginx 会在你的服务器上查找 qwissit-widget.js。因此代码片段写的是 location ^~ /qwissit/——^~ 确保这个路径始终被转发。
  • 修改需重新加载后才生效:nginx -t && nginx -s reload;Apache 用 apachectl configtest && systemctl reload apache2。在 Docker 中如果单独挂载了配置文件,替换该文件(rsync、cp)后容器仍会看到旧版本——这时只能重启容器(docker compose restart <服务>)。
  • Apache:必须启用 proxy、proxy_http、ssl 和 headers 模块(a2enmod proxy proxy_http ssl headers)。这些规则应写在服务器或 VirtualHost 配置中,而不是 .htaccess 中。如果你只能使用 .htaccess,请改用 PHP 文件。
  • PHP 文件:它必须确实位于网站目录中(TYPO3 中为 public/),否则请求会被 CMS 接管。服务器必须把文件后面的路径(PATH_INFO)传给 PHP:Apache 中设置 AcceptPathInfo On(很多主机默认如此),nginx 中在 PHP 规则里这样写:
    location ~ \.php(/|$) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        # … your usual fastcgi_pass / include fastcgi_params
    }

可选:防篡改地验证结果

你想在自己的网站上记录某人通过了测验——例如勾选一节课或发放积分?那就让 Qwissit 确认这个结果。这样谁也无法伪造。

流程如下

  1. 你的页面给测验一个一次性代码,并记住它。
  2. 访客完成测验。Qwissit 亲自检查每个答案;答错的题目会再次出现,直到全部答对。
  3. 结束时,你的页面会收到一份只有 Qwissit 才能签发的凭证,并把它发送到你的服务器。
  4. 你的服务器向 Qwissit 询问该凭证是否真实、是否与你的代码和测验相符。只有这样才会保存结果。

你需要添加什么

两处,都用 PHP。你的访客需要登录(会话),因为结果要归属于某个人。

A) 在测验所在的页面上: 这段代码替代普通代码片段。把 data-set 和 data-course 改成你的测验——数值见上面的代码。

<?php
session_start();   // your visitors are signed in
$nonce = $_SESSION['quiz_nonce']['http'] ??= rtrim(strtr(base64_encode(random_bytes(16)), '+/', '-_'), '=');
?>
<div id="quiz" data-qwissit-widget data-set="12" data-course="13" data-lang="de"
     data-verify="<?= $nonce ?>"></div>
<script src="https://www.qwissit.com/widget/v1/qwissit-widget.js" async></script>
<script>
document.getElementById('quiz').addEventListener('qwissit:finish', function (e) {
  if (!e.detail.passed || !e.detail.token) return;
  fetch('quiz-complete.php', {
    method: 'POST',
    credentials: 'same-origin',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: 'lesson=http&token=' + encodeURIComponent(e.detail.token)
  }).then(function (r) {
    if (r.ok) { /* done: e.g. show a tick */ }
  });
});
</script>

B) 新文件 quiz-complete.php 放在同一目录中。在 QUIZZES 中填入相同的 set 和 course 数值,并在标记处按你网站的方式保存结果。

<?php
// quiz-complete.php – checks the result with Qwissit and saves it only if everything matches
session_start();
const QUIZZES = ['http' => ['set' => 12, 'course' => 13]];   // same values as data-set / data-course

$lesson = (string)($_POST['lesson'] ?? '');
$token = (string)($_POST['token'] ?? '');
$quiz = QUIZZES[$lesson] ?? null;
$nonce = (string)($_SESSION['quiz_nonce'][$lesson] ?? '');
if (!$quiz || $nonce === '' || $token === '') { http_response_code(400); exit; }

$ch = curl_init('https://www.qwissit.com/widget/v1/verify');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query(['token' => $token]),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 4,
]);
$r = json_decode((string)curl_exec($ch), true);
curl_close($ch);

if (!is_array($r)) { http_response_code(503); exit; }   // Qwissit not reachable: save nothing
if (($r['valid'] ?? false) !== true
    || !hash_equals($nonce, (string)($r['nonce'] ?? ''))
    || (int)$r['set'] !== $quiz['set'] || (int)$r['course'] !== $quiz['course']) {
    http_response_code(403); exit;                       // forged, already used, expired or another quiz
}
unset($_SESSION['quiz_nonce'][$lesson]);                 // the code counts only once

// ▶ save the result here, e.g. user + $lesson + date (+ $r['wrong'] = failed attempts)

header('Content-Type: application/json');
echo json_encode(['ok' => true]);

只有当 Qwissit 确认凭证、凭证属于你的一次性代码并来自正确的测验时,这个文件才会保存。之后代码即失效,因此每个结果只计一次。如果暂时无法连接 Qwissit,则不保存任何内容——请让访客稍后再试。凭证有效期为一小时。

需要注意

用于隐私政策的文本

一份可按你的网站调整的建议,不构成法律意见。

直接嵌入

通过你自己的域名(代理)

认证与考试

下一个考试是什么?

已有 19 项考试可以练习,21 项正在投票中。查看所有认证及官方信息,投出你的一票,或推荐你的考试。

查看全部认证