/trunk/.gitattributes |
---|
0,0 → 1,2 |
vendor/**/* linguist-vendored |
/trunk/.gitignore |
---|
0,0 → 1,7 |
vendor/ |
cache/ |
composer.lock |
composer.phar |
Sha3.php |
.phpstan.tmp |
/trunk/ClientChallenge.class.php |
---|
0,0 → 1,126 |
<?php |
/* |
* php_clientchallenge |
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
namespace ViaThinkSoft\RateLimitingChallenge; |
class ClientChallenge { |
private static function tryDownloadPhpSha3() { |
// Download file if required (usually composer should do it) |
if (file_exists(__DIR__.'/Sha3.php')) include_once __DIR__.'/Sha3.php'; |
if (!class_exists('\bb\Sha3\Sha3')) { |
$sha3_lib = file_get_contents('https://raw.githubusercontent.com/danielmarschall/php-sha3/master/src/Sha3.php'); |
if (@file_put_contents(__DIR__.'/Sha3.php', $sha3_lib)) { |
include_once __DIR__.'/Sha3.php'; |
} else { |
eval('?>'.$sha3_lib); |
} |
} |
} |
private static function sha3_512($message, $raw_output=false) { |
if (version_compare(PHP_VERSION, '7.1.0') >= 0) { |
return hash('sha3-512', $message, $raw_output); |
} else { |
self::tryDownloadPhpSha3(); |
return \bb\Sha3\Sha3::hash($message, 512, $raw_output); |
} |
} |
private static function sha3_512_hmac($message, $key, $raw_output=false) { |
// RFC 2104 HMAC |
if (version_compare(PHP_VERSION, '7.1.0') >= 0) { |
return hash_hmac('sha3-512', $message, $key, $raw_output); |
} else { |
self::tryDownloadPhpSha3(); |
return \bb\Sha3\Sha3::hash_hmac($message, $key, 512, $raw_output); |
} |
} |
private static function getOpenTransFileName($ip_target, $random, $server_secret) { |
$dir = defined('VTS_CS_OPEN_TRANS_DIR') ? VTS_CS_OPEN_TRANS_DIR : __DIR__.'/cache'; |
if ($dir == '') $dir = '.'; /** @phpstan-ignore-line */ |
// First, delete challenges which were never completed |
$files = glob($dir.'/vts_client_challenge_*.tmp'); |
$expire = strtotime('-3 DAYS'); |
foreach ($files as $file) { |
if (!is_file($file)) continue; |
if (filemtime($file) > $expire) continue; |
@unlink($file); |
} |
return $dir.'/vts_client_challenge_'.self::sha3_512_hmac($ip_target.'/'.$random, $server_secret).'.tmp'; |
} |
public static function checkValidation($client_response, $max_time=10, $server_secret) { |
if (!is_array($client_response)) throw new \Exception('Challenge response is invalid'); |
if (count($client_response) != 5) throw new \Exception('Challenge response is invalid'); |
list($starttime, $ip_target, $challenge, $answer, $challenge_integrity) = $client_response; |
if (!is_numeric($starttime)) throw new \Exception('Challenge response is invalid'); |
if (!is_string($ip_target)) throw new \Exception('Challenge response is invalid'); |
if (!is_string($challenge)) throw new \Exception('Challenge response is invalid'); |
if (!is_numeric($answer)) throw new \Exception('Challenge response is invalid'); |
if (!is_string($challenge_integrity)) throw new \Exception('Challenge response is invalid'); |
$open_trans_file = self::getOpenTransFileName($ip_target, $answer, $server_secret); |
$current_ip = (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown'); |
if ($ip_target != $current_ip) { |
throw new \Exception("IP address has changed. Please try again. (current IP $current_ip, expected $ip_target)"); |
} else if (time()-$starttime > $max_time) { |
throw new \Exception('Challenge expired. Please try again.'); |
} else if ($challenge_integrity != self::sha3_512_hmac($challenge,$server_secret)) { |
throw new \Exception('Challenge integrity failed'); |
} else if ($challenge !== self::sha3_512($starttime.'/'.$ip_target.'/'.$answer)) { |
throw new \Exception('Wrong answer'); |
} else if (!file_exists($open_trans_file)) { |
throw new \Exception('Challenge submitted twice or transaction missing'); |
} else { |
@unlink($open_trans_file); |
return true; |
} |
} |
public static function createChallenge($complexity=50000, $server_secret) { |
$offset = 0; // doesn't matter |
$min = $offset; |
$max = $offset + $complexity; |
$starttime = time(); |
$random = rand($min,$max); // TODO: cryptographic rand |
$ip_target = $_SERVER['REMOTE_ADDR']; |
$challenge = self::sha3_512($starttime.'/'.$ip_target.'/'.$random); |
$challenge_integrity = self::sha3_512_hmac($challenge,$server_secret); |
$send_to_client = array($starttime, $ip_target, $challenge, $min, $max, $challenge_integrity); |
$open_trans_file = self::getOpenTransFileName($ip_target, $random, $server_secret); |
if (@file_put_contents($open_trans_file, '') === false) { |
throw new \Exception("Cannot write $open_trans_file"); |
} |
return $send_to_client; |
} |
} |
/trunk/ClientChallenge.js |
---|
0,0 → 1,46 |
/* |
* php_clientchallenge |
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
function vts_validated_call(getChallengeScript, callback, params, error_cb) { |
$.ajax({ |
type: "POST", |
url: getChallengeScript, |
data: { |
}, |
success: function(data) { |
if ("error" in data) { |
error_cb(null,null,data["error"]); |
return; |
} |
var starttime = data[0]; |
var ip_target = data[1]; |
var challenge = data[2]; |
var min = data[3]; |
var max = data[4]; |
var challenge_integrity = data[5]; |
for (i=min; i<=max; i++) { |
if (challenge == sha3_512(starttime+"/"+ip_target+"/"+i)) { |
var answer = i; |
var vts_validation_result = JSON.stringify([starttime, ip_target, challenge, answer, challenge_integrity]); |
callback(params, vts_validation_result); |
break; |
} |
} |
}, |
error: error_cb |
}); |
} |
/trunk/LICENSE |
---|
0,0 → 1,202 |
Apache License |
Version 2.0, January 2004 |
http://www.apache.org/licenses/ |
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
1. Definitions. |
"License" shall mean the terms and conditions for use, reproduction, |
and distribution as defined by Sections 1 through 9 of this document. |
"Licensor" shall mean the copyright owner or entity authorized by |
the copyright owner that is granting the License. |
"Legal Entity" shall mean the union of the acting entity and all |
other entities that control, are controlled by, or are under common |
control with that entity. For the purposes of this definition, |
"control" means (i) the power, direct or indirect, to cause the |
direction or management of such entity, whether by contract or |
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
outstanding shares, or (iii) beneficial ownership of such entity. |
"You" (or "Your") shall mean an individual or Legal Entity |
exercising permissions granted by this License. |
"Source" form shall mean the preferred form for making modifications, |
including but not limited to software source code, documentation |
source, and configuration files. |
"Object" form shall mean any form resulting from mechanical |
transformation or translation of a Source form, including but |
not limited to compiled object code, generated documentation, |
and conversions to other media types. |
"Work" shall mean the work of authorship, whether in Source or |
Object form, made available under the License, as indicated by a |
copyright notice that is included in or attached to the work |
(an example is provided in the Appendix below). |
"Derivative Works" shall mean any work, whether in Source or Object |
form, that is based on (or derived from) the Work and for which the |
editorial revisions, annotations, elaborations, or other modifications |
represent, as a whole, an original work of authorship. For the purposes |
of this License, Derivative Works shall not include works that remain |
separable from, or merely link (or bind by name) to the interfaces of, |
the Work and Derivative Works thereof. |
"Contribution" shall mean any work of authorship, including |
the original version of the Work and any modifications or additions |
to that Work or Derivative Works thereof, that is intentionally |
submitted to Licensor for inclusion in the Work by the copyright owner |
or by an individual or Legal Entity authorized to submit on behalf of |
the copyright owner. For the purposes of this definition, "submitted" |
means any form of electronic, verbal, or written communication sent |
to the Licensor or its representatives, including but not limited to |
communication on electronic mailing lists, source code control systems, |
and issue tracking systems that are managed by, or on behalf of, the |
Licensor for the purpose of discussing and improving the Work, but |
excluding communication that is conspicuously marked or otherwise |
designated in writing by the copyright owner as "Not a Contribution." |
"Contributor" shall mean Licensor and any individual or Legal Entity |
on behalf of whom a Contribution has been received by Licensor and |
subsequently incorporated within the Work. |
2. Grant of Copyright License. Subject to the terms and conditions of |
this License, each Contributor hereby grants to You a perpetual, |
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
copyright license to reproduce, prepare Derivative Works of, |
publicly display, publicly perform, sublicense, and distribute the |
Work and such Derivative Works in Source or Object form. |
3. Grant of Patent License. Subject to the terms and conditions of |
this License, each Contributor hereby grants to You a perpetual, |
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
(except as stated in this section) patent license to make, have made, |
use, offer to sell, sell, import, and otherwise transfer the Work, |
where such license applies only to those patent claims licensable |
by such Contributor that are necessarily infringed by their |
Contribution(s) alone or by combination of their Contribution(s) |
with the Work to which such Contribution(s) was submitted. If You |
institute patent litigation against any entity (including a |
cross-claim or counterclaim in a lawsuit) alleging that the Work |
or a Contribution incorporated within the Work constitutes direct |
or contributory patent infringement, then any patent licenses |
granted to You under this License for that Work shall terminate |
as of the date such litigation is filed. |
4. Redistribution. You may reproduce and distribute copies of the |
Work or Derivative Works thereof in any medium, with or without |
modifications, and in Source or Object form, provided that You |
meet the following conditions: |
(a) You must give any other recipients of the Work or |
Derivative Works a copy of this License; and |
(b) You must cause any modified files to carry prominent notices |
stating that You changed the files; and |
(c) You must retain, in the Source form of any Derivative Works |
that You distribute, all copyright, patent, trademark, and |
attribution notices from the Source form of the Work, |
excluding those notices that do not pertain to any part of |
the Derivative Works; and |
(d) If the Work includes a "NOTICE" text file as part of its |
distribution, then any Derivative Works that You distribute must |
include a readable copy of the attribution notices contained |
within such NOTICE file, excluding those notices that do not |
pertain to any part of the Derivative Works, in at least one |
of the following places: within a NOTICE text file distributed |
as part of the Derivative Works; within the Source form or |
documentation, if provided along with the Derivative Works; or, |
within a display generated by the Derivative Works, if and |
wherever such third-party notices normally appear. The contents |
of the NOTICE file are for informational purposes only and |
do not modify the License. You may add Your own attribution |
notices within Derivative Works that You distribute, alongside |
or as an addendum to the NOTICE text from the Work, provided |
that such additional attribution notices cannot be construed |
as modifying the License. |
You may add Your own copyright statement to Your modifications and |
may provide additional or different license terms and conditions |
for use, reproduction, or distribution of Your modifications, or |
for any such Derivative Works as a whole, provided Your use, |
reproduction, and distribution of the Work otherwise complies with |
the conditions stated in this License. |
5. Submission of Contributions. Unless You explicitly state otherwise, |
any Contribution intentionally submitted for inclusion in the Work |
by You to the Licensor shall be under the terms and conditions of |
this License, without any additional terms or conditions. |
Notwithstanding the above, nothing herein shall supersede or modify |
the terms of any separate license agreement you may have executed |
with Licensor regarding such Contributions. |
6. Trademarks. This License does not grant permission to use the trade |
names, trademarks, service marks, or product names of the Licensor, |
except as required for reasonable and customary use in describing the |
origin of the Work and reproducing the content of the NOTICE file. |
7. Disclaimer of Warranty. Unless required by applicable law or |
agreed to in writing, Licensor provides the Work (and each |
Contributor provides its Contributions) on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
implied, including, without limitation, any warranties or conditions |
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
PARTICULAR PURPOSE. You are solely responsible for determining the |
appropriateness of using or redistributing the Work and assume any |
risks associated with Your exercise of permissions under this License. |
8. Limitation of Liability. In no event and under no legal theory, |
whether in tort (including negligence), contract, or otherwise, |
unless required by applicable law (such as deliberate and grossly |
negligent acts) or agreed to in writing, shall any Contributor be |
liable to You for damages, including any direct, indirect, special, |
incidental, or consequential damages of any character arising as a |
result of this License or out of the use or inability to use the |
Work (including but not limited to damages for loss of goodwill, |
work stoppage, computer failure or malfunction, or any and all |
other commercial damages or losses), even if such Contributor |
has been advised of the possibility of such damages. |
9. Accepting Warranty or Additional Liability. While redistributing |
the Work or Derivative Works thereof, You may choose to offer, |
and charge a fee for, acceptance of support, warranty, indemnity, |
or other liability obligations and/or rights consistent with this |
License. However, in accepting such obligations, You may act only |
on Your own behalf and on Your sole responsibility, not on behalf |
of any other Contributor, and only if You agree to indemnify, |
defend, and hold each Contributor harmless for any liability |
incurred by, or claims asserted against, such Contributor by reason |
of your accepting any such warranty or additional liability. |
END OF TERMS AND CONDITIONS |
APPENDIX: How to apply the Apache License to your work. |
To apply the Apache License to your work, attach the following |
boilerplate notice, with the fields enclosed by brackets "[]" |
replaced with your own identifying information. (Don't include |
the brackets!) The text should be enclosed in the appropriate |
comment syntax for the file format. We also recommend that a |
file or class name and description of purpose be included on the |
same "printed page" as the copyright notice for easier |
identification within third-party archives. |
Copyright 2018 Daniel Marschall, ViaThinkSoft |
Licensed under the Apache License, Version 2.0 (the "License"); |
you may not use this file except in compliance with the License. |
You may obtain a copy of the License at |
http://www.apache.org/licenses/LICENSE-2.0 |
Unless required by applicable law or agreed to in writing, software |
distributed under the License is distributed on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
See the License for the specific language governing permissions and |
limitations under the License. |
/trunk/README.md |
---|
0,0 → 1,71 |
# Server requests using client challenges |
### What is it? |
This PHP/JavaScript package can be used to add client challenges on top of your |
AJAX requests to protect your scripts against brute-force or DoS attacks. |
It can also protect your server against resource starvation attacks, for example, |
if you have a login script that uses a complex hash algorithm like BCrypt. |
### Usage example |
A usage example is located in the directory example/ |
### System requirements |
- PHP-compatible web server (tested with Apache 2, nginx, and Microsoft IIS) |
- PHP 7.0 or higher (also tested with PHP 8.0) |
- Independent of operating system (tested with Windows, Linux, and macOS X) |
### Program flow |
#### 1. Request from Client to Server (Get Challenge) |
Request parameters: |
- None |
The server will generate a secret random number between Min and Max. |
The difference between Min and Max is the complexity constant. |
Response: |
- Current time ("Start time") |
- IP address of the client |
- Challenge = `Hash(StartTime + IP address + Random number)` |
- Min value |
- Max value |
- Challenge integrity = `Hash_HMAC(Challenge, ServerSecret)` |
Additionally, the server will create a "transaction file" (which prevents a replay attack). The filename is `Hash_HMAC(IP+Random, ServerSecret)`. |
The client will now brute-force all values to find the random value between Min and Max. |
#### 2. Request from Client to Server (Solve Challenge and request the resource) |
Request parameters: |
- StartTime (as received previously from the server) |
- IP address of the client (as received previously from the server) |
- Challenge (as received previously from server) |
- Answer (the random number found) |
- Challenge Integrity (as received previously from the server) |
The server will do: |
- Check if parameters exist and have the correct data type |
- Verify that the IP address is the same, otherwise return the error "IP address changed" |
- Verify StartTime is not older than "X" minutes*, otherwise return the error "Challenge expired" |
- Verify that the challenge integrity fits the HMAC of the Challenge |
- Check if the challenge was solved, i.e. Original Challenge matches `Hash(StartTime + IP + Answer)` |
- Check if the transaction file exists, otherwise return the error "Challenge submitted twice" |
- If all is OK, delete the transaction file (to prevent the answer is sent again) and grant access to the resource |
Note: Depending on when you solve the challenge, you should decide on a fitting timeout value, e.g. |
- When the challenge is solved once the login/contact/... form is shown -> choose a timeout value of 10 minutes. The usage of a "transaction file" is important, because the same challenge can be submitted within 10 minutes. |
- When the challenge is solved during the pressing of the "log in/send/..." button -> choose a timeout value of 10-30 seconds (depending on what your complexity constant is and how fast the client CPU is). Usage of "transaction file" is still recommended, but not as important. |
### Reporting a bug |
You can file a bug report here: |
- https://www.viathinksoft.com/thinkbug/thinkbug.php?id=119 |
- https://www.viathinksoft.com/contact/daniel-marschall |
- https://github.com/danielmarschall/php_clientchallenge/issues |
### Support |
If you have any questions or need help, please contact us: |
https://www.viathinksoft.com/contact/daniel-marschall |
/trunk/cache/.gitignore |
---|
--- cache (nonexistent) |
+++ cache (revision 13) |
/cache |
---|
Property changes: |
Added: svn:ignore |
+*.tmp |
+ |
/trunk/composer.json |
---|
0,0 → 1,28 |
{ |
"name": "danielmarschall/php_clientchallenge", |
"description": "Server requests using client-challenges in order to mitigate resource starvation", |
"version": "1.1.1", |
"type": "package", |
"homepage": "https://www.viathinksoft.com/projects/php_clientchallenge", |
"authors": [ |
{ |
"name": "Daniel Marschall", |
"email": "info@daniel-marschall.de", |
"homepage": "https://www.daniel-marschall.de/" |
} |
], |
"license": [ |
"Apache-2.0" |
], |
"prefer-dist": true, |
"require": { |
"php": ">=7.0", |
"danielmarschall/php-sha3": "*@dev" |
}, |
"require-dev": { |
"phpstan/phpstan": "^1.8" |
}, |
"autoload": { |
"classmap" : ["ClientChallenge.class.php"] |
} |
} |
/trunk/example/ajax_example.php |
---|
0,0 → 1,49 |
<?php |
/* |
* php_clientchallenge |
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
if (file_exists(__DIR__ . '/../vendor/autoload.php')) { |
require_once __DIR__ . '/../vendor/autoload.php'; |
} |
require_once __DIR__ . '/../ClientChallenge.class.php'; |
require_once __DIR__ . '/config.inc.php'; |
if (isset($_REQUEST['action']) && ($_REQUEST['action'] === 'add_numbers')) { |
// Check request field "vts_validation_result" for valid response of the Challenge |
try { |
if (!isset($_REQUEST['vts_validation_result'])) throw new \Exception('No challenge response found'); |
$client_response = @json_decode($_REQUEST['vts_validation_result'], true); |
\ViaThinkSoft\RateLimitingChallenge\ClientChallenge::checkValidation($client_response, MAX_TIME, VTS_CS_SERVER_SECRET); |
} catch (\Exception $e) { |
$res = array("error" => $e->getMessage()); |
header('Content-Type:application/json'); |
die(json_encode($res)); |
} |
// Do your stuff here. Example: |
$a = $_REQUEST['a']; |
$b = $_REQUEST['b']; |
$res = array("result" => ($a+$b)); |
header('Content-Type:application/json'); |
die(json_encode($res)); |
} |
/trunk/example/ajax_get_challenge.php |
---|
0,0 → 1,35 |
<?php |
/* |
* php_clientchallenge |
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
if (file_exists(__DIR__ . '/../vendor/autoload.php')) { |
require_once __DIR__ . '/../vendor/autoload.php'; |
} |
require_once __DIR__ . '/../ClientChallenge.class.php'; |
require_once __DIR__ . '/config.inc.php'; |
try { |
$res = \ViaThinkSoft\RateLimitingChallenge\ClientChallenge::createChallenge(COMPLEXITY, VTS_CS_SERVER_SECRET); |
} catch (\Exception $e) { |
$res = array("error" => $e->getMessage()); |
} |
header('Content-Type:application/json'); |
die(json_encode($res)); |
/trunk/example/config.inc.php |
---|
0,0 → 1,23 |
<?php |
/* |
* php_clientchallenge |
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
define('VTS_CS_OPEN_TRANS_DIR', __DIR__.'/../cache/'); |
define('VTS_CS_SERVER_SECRET', '1234567890'); // PLEASE CHANGE THIS VALUE TO SOMETHING RANDOM! |
define('MAX_TIME', 15); // seconds |
define('COMPLEXITY', 50000); |
/trunk/example/index.html |
---|
0,0 → 1,64 |
<!DOCTYPE HTML> |
<html> |
<head> |
<title>Example of server request using Client-Challenge in order to mitigate resource starvation</title> |
<meta charset="utf-8"> |
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> |
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha3/0.8.0/sha3.min.js"></script> |
<script src="../ClientChallenge.js"></script> |
<script> |
let error_cb = function (request, status, error) { |
$("#out").val("Error!"); |
alert(error); |
} |
let callback = function(params, vts_validation_result) { |
$.ajax({ |
type: "POST", |
url: "ajax_example.php", |
data: { |
// This is required: |
"vts_validation_result": vts_validation_result, |
// This you can set yourself: |
"action": "add_numbers", |
"a": params['a'], |
"b": params['b'] |
}, |
success: function(data) { |
if ("error" in data) { |
error_cb(null,null,data["error"]); |
} else { |
$("#out").val(data["result"]); |
} |
}, |
error: error_cb |
}); |
} |
function calc() { |
var a = $("#in_a").val(); |
var b = $("#in_b").val(); |
var params = { |
"a": a, |
"b": b |
}; |
$("#out").val("Please wait..."); |
vts_validated_call("ajax_get_challenge.php", callback, params, error_cb); |
} |
</script> |
</head> |
<body> |
<h2>Example of server request using Client-Challenge in order to mitigate resource starvation</h2> |
<p><input id="in_a" value="2"> + <input id="in_b" value="3"> = <input id="out"> <input type="button" onclick="calc()" value="Calculate"></p> |
</body> |
</html> |
/trunk/phpstan.neon.dist |
---|
0,0 → 1,19 |
parameters: |
level: 5 |
fileExtensions: |
- php |
paths: |
- . |
excludePaths: |
analyse: |
- Sha3.php |
- vendor |
analyseAndScan: |
- .phpstan.tmp |
tmpDir: .phpstan.tmp |
bootstrapFiles: |
- example/config.inc.php |
ignoreErrors: |
#- '#is always (true|false)\.#' |
#- '#Call to function assert\(\) with false will always evaluate to false\.#' |
#- '#with no typehint specified\.#' |
/trunk/. |
---|
Property changes: |
Added: svn:ignore |
+vendor |
+composer.lock |
+composer.phar |
+.phpstan.tmp |
+phpstan.neon |
+Sha3.php |
+ |