mrimann / remote-script-verifier

支持验证远程脚本的行为和输出 - 例如在问答中使用。

v1.2.0 2016-10-30 21:14 UTC

This package is auto-updated.

Last update: 2024-09-06 10:38:50 UTC


README

Latest Stable Version Total Downloads Build Status

它做什么?

该软件包包含一些辅助类,以支持一种特殊的在线挑战,其中参与者需要创建一个脚本以解决某些问题。此处包含的代码有助于问答作者验证输出并向参与者展示一些美观的检查结果。

如何使用它?

基本来说,脚本只需要提供指向任何服务器上Web服务器的有效URL,该服务器在该URL下提供脚本,该脚本可以解决给定任务。以下是一些可以包含在您的问答页面中的代码片段

获取URL并启动验证器

我预计您有一个名为“url”的输入字段的表单,该字段通过POST方式发送到问答脚本。在问答脚本中,以下代码初始化验证器

$url = $_POST['url'];
echo 'OK, let\'s try to verify the URL: "' . htmlspecialchars($url) . '"';
$verifier = new \Mrimann\RemoteScriptVerifier\Verifier();
$verifier->setBaseUrl($url);

一些安全措施

网络上有许多非常好的人 - 但也有一些想惹麻烦的人...因此,RemoteScriptVerifier提供了一些节流和限制功能。这意味着每个脚本URL每小时只能请求n次 - 同时每小时也只允许来自相同源IP地址的n个请求。

此功能必须明确启用和配置。这是唯一需要创建数据库的功能(必须包含名为“logging”的表,请参阅res/logging.sql以获取DB模式)。

// we want to use the throttling + logging stuff
$verifier->setDatabaseHost('localhost');
$verifier->setDatabaseUser('foobar');
$verifier->setDatabasePassword('ultrastrongsecurity');
$verifier->setDatabaseName('foobar');
$verifier->enableThrottlingAndLogging();

// if initializing would have failed, we would have some failed tests
if ($verifier->passedAllTests() == TRUE) {
	$verifier->checkRequestAgainstThrottlingLimits(
		$_SERVER['REMOTE_ADDR'],
		$url
	);
}

// if the request did not pass the above barrier test, we should give up now
if ($verifier->passedAllTests() != TRUE) {
	$verifier->addNewFailedResult('Given up for now...');
}

进行一些基本检查

RemoteScriptVerifier软件包包含一些基本检查,您可以通过以下方式执行它们

// check basic availability
$basicChecks = new \Mrimann\RemoteScriptVerifier\Checks($verifier);
$basicChecks->executeTestForNonEmptyUrl();
$basicChecks->executeTestForValidLookingUrl();
// this is sample content and depends on your challenge, what's needed
$requiredGetParameters = array(
	'x' => rand(1,99),
	'y' => rand(1,99)
);
// checks if the script is returning a HTTP 200 status code if called with valid input
$basicChecks->executeTestForAvailabilityOfTheRemoteScript($requiredGetParameters);
if ($verifier->passedAllTests() != TRUE) {
	$verifier->addNewFailedResult('Giving up...');
}

现在执行您自己的第一个检查

基本上,您现在可以根据您设置的挑战请求远程脚本,重复多次。为了验证输入验证,我正在运行如下代码

// check the input validation of the remote script
$correctErrorReasonPhrase = 'I don\'t like your input...';
$res = $verifier->fetchRemoteScript(
	array()
);
if ($res->getStatusCode() == 500 && $res->getReasonPhrase() == $correctErrorReasonPhrase) {
	$verifier->addNewSuccessfulResult('Throws error when called with no GET parameters.');
} else {
	$verifier->addNewFailedResult('Uh, there seems to be missing some input validation!');
}

由于挑战要求一个脚本接受两个GET参数,因此如果没有提供任何参数,它必须失败。这正是我们通过此代码进行的检查。您还可以看到如何在您自己的检查中报告错误:只需使用带有一些描述性文本的addNewSuccessfulResultaddNewFailedResult即可。这些将稍后显示给用户(请参阅下一节)。

一旦验证脚本在向它扔垃圾时表现正确,就到了验证问答的参与者是否成功解决了您发起的挑战的时候了。例如,(好吧,非常简单)挑战可以是“获取两个随机整数参数x和y,返回这两个数字之和”,而检查这个的代码可以是

// let's check the output of the script to be correct
$x = rand(1, 999);
$y = rand(1, 999);
$res = $verifier->fetchRemoteScript(
	array(
		'x' => $x,
		'y' => $y
	)
);
// if you're about to conduct multple tests, save the response of the script
// and check against this, instead of re-fetching the script from the remote
// server over and over again
$rawOoutput = $res->getBody();

// check the calculation result
if ($output == $x + $y) {
	$verifier->addNewSuccessfulResult('Your calculation looks fine.');
} else {
	$verifier->addNewFailedResult('Looks like your calculation is not correct yet.');
}

向用户显示结果

当然,用户希望看到他对所取得的成就的响应。以下是如何将这些结果带回给参与者的方法

// show the check results
echo '<ul class="results">';
while ($checkResult = $verifier->getCheckResults()->current()) {
	echo '<li class="' . $checkResult->getStatus() . '">' . $checkResult->getMessage() . '</li>';
	$verifier->getCheckResults()->next();
}
echo '</ul>';

以上将输出单个检查结果,如果通过CSS进行样式化,它们将已经表明一切顺利。但最终用户基本上只对获得下一阶段的链接感兴趣,所以让我们给他或她提供这个链接

// show the link if all checks were passed
if ($verifier->passedAllTests() === TRUE) {
	$verifier->logVerification('success');
	echo '<b>Yippie aye yeah. Here\'s the link to the final stage: <a href="#">GO GO GO</a></b>';
} else {
	$verifier->logVerification(
		$verifier->getErrorCount() . ' errors'
	);
	echo '<b>Seems like something went wrong - sorry, there\'s no link for you now - try again...</b>';
}

上述内容包含了对logVerification的两次调用,该调用仅在您激活了上述节流和限制功能时需要。它将扩展上面创建的日志条目,包含验证的最终结果——因此您应该在数据库中看到,一个人尝试了多少次,以及他的脚本在验证时产生了多少错误。

如何支持

如果您觉得我的东西有用,如果您能查看我的支持页面,了解您如何让我开心,我会非常高兴。

当然,整个代码都有改进的空间。如果您发现了一个bug,或者认为事情可以简化或改进,只需打开一个问题——如果可能的话,提交一个pull请求。这样,每个人都可以从您的贡献中受益。

许可证

此存储库的整个代码都在MIT许可证下授权,详细信息请参阅LICENSE文件。