Schützen Sie Ihre Formulare mit Formularschlüsseln

WBOY
Freigeben: 2023-09-07 21:52:01
Original
1412 Leute haben es durchsucht

Sicherheit ist ein heißes Thema. Die Sicherung Ihrer Website ist für jede Webanwendung äußerst wichtig. Tatsächlich verbringe ich 70 % meiner Zeit damit, Bewerbungen zu sichern. Eines der wichtigsten Dinge, die wir schützen müssen, sind Formulare. Heute prüfen wir eine Möglichkeit, XSS (Cross-Site-Scripting) und Cross-Site-Request-Forgery auf Ihren Formularen zu verhindern.

Warum?

POST-Daten können von einer Website an eine andere gesendet werden. Warum ist das schlimm? Eine einfache Szene...

Ein auf Ihrer Website angemeldeter Benutzer besucht während seiner Sitzung eine andere Website. Die Website kann POST-Daten an Ihre Website senden – beispielsweise mithilfe von AJAX. Da der Benutzer auf Ihrer Website angemeldet ist, können auch andere Websites Beitragsdaten an ein sicheres Formular senden, auf das nur Benutzer zugreifen können, die angemeldet sind.

Wir müssen unsere Seiten auch mithilfe von cURL vor Angriffen schützen

Wie lösen wir dieses Problem?

Mit Formularschlüsseln! Wir fügen jedem Formular einen speziellen Hash (Formularschlüssel) hinzu, um sicherzustellen, dass die Daten nur verarbeitet werden, wenn sie von Ihrer Website gesendet werden. Sobald das Formular übermittelt wurde, validiert unser PHP-Skript den übermittelten Formularschlüssel anhand des Formularschlüssels, den wir in der Sitzung festgelegt haben.

Was wir tun müssen:

  1. Fügen Sie jedem Formular Formularschlüssel hinzu.
  2. Formularschlüssel in der Sitzung speichern.
  3. Überprüfen Sie den Formularschlüssel nach dem Absenden des Formulars.

Schritt 1: Einfaches Formular

Zuerst benötigen wir ein einfaches Formular zur Demonstration. Eines der wichtigsten Formulare, die wir schützen müssen, ist das Anmeldeformular. Anmeldeformulare sind anfällig für Brute-Force-Angriffe. Erstellen Sie eine neue Datei und speichern Sie sie als index.php in Ihrem Web-Stammverzeichnis. Fügen Sie den folgenden Code im Textkörper hinzu:

	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
		<title>Securing forms with form keys</title>
	</head>
	<body>
		<form action="" method="post">
		<dl>
			<dt><label for="username">Username:</label></dt>
			<dd><input type="text" name="username" id="username" /></dd>
			<dt><label for="username">Password:</label></dt>
			<dd><input type="password" name="password" id="password" /></dd>
			<dt></dt>
			<dd><input type="submit" value="Login" /></dd>
		</dl>
		</form>
	</body>
	</html>
Nach dem Login kopieren

Jetzt haben wir eine einfache XHTML-Seite mit einem Anmeldeformular. Wenn Sie Formularschlüssel auf Ihrer Website verwenden möchten, können Sie das obige Skript durch Ihre eigene Anmeldeseite ersetzen. Kommen wir nun zur eigentlichen Aktion.

Schritt 2: Erstellen Sie die Klasse

Wir erstellen eine PHP-Klasse für den Formularschlüssel. Da jede Seite nur einenFormularschlüssel enthalten kann, können wir einen Singleton für unsere Klasse erstellen, um sicherzustellen, dass unsere Klasse korrekt verwendet wird. Da das Erstellen von Singletons ein fortgeschritteneres OOP-Thema ist, überspringen wir diesen Teil. Erstellen Sie eine neue Datei mit dem Namen formkey.class.php und legen Sie sie in Ihrem Web-Stammverzeichnis ab. Jetzt müssen wir über die Funktionalität nachdenken, die wir benötigen. Zuerst benötigen wir eine Funktion zum Generieren des Formularschlüssels, damit wir ihn in das Formular einfügen können. Fügen Sie den folgenden Code in Ihre PHP-Datei ein:

<?php

//You can of course choose any name for your class or integrate it in something like a functions or base class
class formKey
{
	//Here we store the generated form key
	private $formKey;
	
	//Here we store the old form key (more info at step 4)
	private $old_formKey;
	
	//Function to generate the form key
	private function generateKey()
	{
		
	}
}
?>
Nach dem Login kopieren

Oben sehen Sie eine Klasse mit drei Teilen: zwei Variablen und einer Funktion. Wir machen diese Funktion privat, da sie nur von der Ausgabefunktion verwendet wird, die wir später erstellen. In diesen beiden Variablen werden wir die Formularschlüssel speichern. Sie sind außerdem privat, da sie nur von Funktionen innerhalb unserer Klasse verwendet werden können.

Jetzt müssen wir einen Weg finden, den Formularschlüssel zu generieren. Da unser Formularschlüssel eindeutig sein muss (andernfalls hätten wir keine Sicherheit), binden wir den Schlüssel an den Benutzer, indem wir eine Kombination aus der IP-Adresse des Benutzers verwenden, mt_rand() verwenden, um ihn eindeutig zu machen, und die Funktion uniqid() verwenden um es einzigartiger zu machen. Wir verschlüsseln diese Informationen auch mit md5(), um einen eindeutigen Hash-Wert zu erstellen, den wir dann in unsere Seite einfügen. Da wir md5() verwendet haben, kann der Benutzer nicht sehen, was wir zum Generieren des Schlüssels verwendet haben. Gesamtes Feature:

//Function to generate the form key
private function generateKey()
{
	//Get the IP-address of the user
	$ip = $_SERVER['REMOTE_ADDR'];
	
	//We use mt_rand() instead of rand() because it is better for generating random numbers.
	//We use 'true' to get a longer string.
	//See http://www.php.net/mt_rand for a precise description of the function and more examples.
	$uniqid = uniqid(mt_rand(), true);
	
	//Return the hash
	return md5($ip . $uniqid);
}
Nach dem Login kopieren

Fügen Sie den obigen Code in Ihre formkey.class.php-Datei ein. Ersetzen Sie die Funktion durch die neue Funktion.

Schritt 3: Geben Sie den Formularschlüssel in das Formular ein

Für diesen Schritt erstellen wir eine neue Funktion, die versteckte HTML-Felder mithilfe von Formularschlüsseln ausgibt. Diese Funktion besteht aus drei Schritten:

  1. Generieren Sie Formularschlüssel mit unserer Funktion „generateKey()“.
  2. Speichern Sie den Formularschlüssel in der Variablen $formKey und in der Sitzung.
  3. HTML-Felder ausgeben.

Wir nennen die Funktion outputKey() und machen sie öffentlich, da wir sie außerhalb der Klasse verwenden müssen. Unsere Funktion ruft die private Funktion generateKey() auf, um einen neuen Formularschlüssel zu generieren und ihn in der lokalen Sitzung zu speichern. Abschließend erstellen wir den XHTML-Code. Fügen Sie nun den folgenden Code in unserer PHP-Klasse hinzu:

//Function to output the form key
public function outputKey()
{
	//Generate the key and store it inside the class
	$this->formKey = $this->generateKey();
	//Store the form key in the session
	$_SESSION['form_key'] = $this->formKey;
	
	//Output the form key
	echo "<input type='hidden' name='form_key' id='form_key' value='".$this->formKey."' />";
}
Nach dem Login kopieren

Jetzt fügen wir den Formularschlüssel zu unserem Anmeldeformular hinzu, um die Sicherheit zu gewährleisten. Wir müssen diese Klasse in die Datei index.php aufnehmen. Wir müssen die Sitzung auch starten, da unsere Klasse die Sitzung zum Speichern der generierten Schlüssel verwendet. Dazu fügen wir über den Doctype- und Head-Tags den folgenden Code ein:

<?php
//Start the session
session_start();
//Require the class
require('formkey.class.php');
//Start the class
$formKey = new formKey();
?>
Nach dem Login kopieren

Der obige Code ist ziemlich selbsterklärend. Wir starten die Sitzung (da wir den Formularschlüssel speichern) und laden die PHP-Klassendatei. Danach starten wir die Klasse mit new formKey(), wodurch unsere Klasse erstellt und in $formKey gespeichert wird. Jetzt müssen wir nur noch das Formular bearbeiten, sodass es den Formularschlüssel enthält:

<form action="" method="post">
<dl>
	<?php $formKey->outputKey(); ?>
	<dt><label for="username">Username:</label></dt>
	<dd><input type="text" name="username" id="username" /></dd>
	<dt><label for="username">Password:</label></dt>
	<dd>input type="password" name="password" id="password" /></dd>
<dl>
</form>
Nach dem Login kopieren

仅此而已!因为我们创建了函数 outputKey(),所以我们只需将它包含在表单中即可。我们可以在每个表单中使用表单键,只需添加 outputKey(); ?> 现在只需查看网页的源代码,您就可以看到表单上附加了一个表单密钥。剩下的唯一步骤是验证请求。

第 4 步:验证

我们不会验证整个表单;只有表单键。验证表单是基本的 PHP 操作,并且可以在网络上找到教程。让我们验证表单密钥。因为我们的“generateKey”函数会覆盖会话值,所以我们向 PHP 类添加一个构造函数。创建(或构造)我们的类时将调用构造函数。在我们创建新密钥之前,构造函数会将前一个密钥存储在类中;所以我们将始终拥有以前的表单密钥来验证我们的表单。如果我们不这样做,我们将无法验证表单密钥。将以下 PHP 函数添加到您的类中:

//The constructor stores the form key (if one exists) in our class variable.
function __construct()
{
	//We need the previous key so we store it
	if(isset($_SESSION['form_key']))
	{
		$this->old_formKey = $_SESSION['form_key'];
	}
}
Nach dem Login kopieren

构造函数应始终命名为__construct()。当调用构造函数时,我们检查是否设置了会话,如果是,我们将其本地存储在 old_formKey 变量中。

现在我们可以验证表单密钥了。我们在类中创建一个基本函数来验证表单密钥。这个函数也应该是公共的,因为我们将在类之外使用它。该函数将根据表单键的存储值验证表单键的 POST 值。将此函数添加到 PHP 类中:

//Function that validated the form key POST data
public function validate()
{
	//We use the old formKey and not the new generated version
	if($_POST['form_key'] == $this->old_formKey)
	{
		//The key is valid, return true.
		return true;
	}
	else
	{
		//The key is invalid, return false.
		return false;
	}
}
Nach dem Login kopieren

index.php中,我们使用刚刚在类中创建的函数来验证表单密钥。当然,我们仅在 POST 请求后进行验证。在 $formKey = new formKey(); 后添加以下代码

$error = 'No error';

//Is request?
if($_SERVER['REQUEST_METHOD'] == 'post')
{
	//Validate the form key
	if(!isset($_POST['form_key']) || !$formKey->validate())
	{
		//Form key is invalid, show an error
		$error = 'Form key error!';
	}
	else
	{
		//Do the rest of your validation here
		$error = 'No form key error!';
	}
}
Nach dem Login kopieren

我们创建了一个变量$error来存储我们的错误消息。如果已发送 POST 请求,我们将使用 $formKey->validate() 验证表单密钥。如果返回 false,则表单键无效,并且我们会显示错误。请注意,我们仅验证表单密钥 - 您需要自己验证表单的其余部分。

在 HTML 中,您可以放置​​以下代码来显示错误消息:

	<div><?php if($error) { echo($error); } ?></div>
Nach dem Login kopieren

这将回显 $error 变量(如果已设置)。

Schützen Sie Ihre Formulare mit Formularschlüsseln

如果您启动服务器并转到index.php,您将看到我们的表单和消息“无错误”。当您提交表单时,您将看到消息“无表单键错误”,因为它是有效的 POST 请求。现在尝试重新加载页面并在浏览器请求再次发送 POST 数据时接受。您将看到我们的脚本触发了一条错误消息:“表单键错误!”现在,您的表单可以免受来自其他网站的输入和页面重新加载错误的影响!刷新后也会显示该错误,因为我们提交表单后生成了新的表单密钥。这很好,因为现在用户不会意外地将表单发布两次。

完整代码

以下是完整的 PHP 和 HTML 代码:

index.php


	



	
	Securing forms with form keys


	
outputKey(); ?>
Nach dem Login kopieren

fomrkey.class.php

<?php

//You can of course choose any name for your class or integrate it in something like a functions or base class
class formKey
{
	//Here we store the generated form key
	private $formKey;
	
	//Here we store the old form key (more info at step 4)
	private $old_formKey;
	
	//The constructor stores the form key (if one excists) in our class variable
	function __construct()
	{
		//We need the previous key so we store it
		if(isset($_SESSION['form_key']))
		{
			$this->old_formKey = $_SESSION['form_key'];
		}
	}

	//Function to generate the form key
	private function generateKey()
	{
		//Get the IP-address of the user
		$ip = $_SERVER['REMOTE_ADDR'];
		
		//We use mt_rand() instead of rand() because it is better for generating random numbers.
		//We use 'true' to get a longer string.
		//See http://www.php.net/mt_rand for a precise description of the function and more examples.
		$uniqid = uniqid(mt_rand(), true);
		
		//Return the hash
		return md5($ip . $uniqid);
	}

	
	//Function to output the form key
	public function outputKey()
	{
		//Generate the key and store it inside the class
		$this->formKey = $this->generateKey();
		//Store the form key in the session
		$_SESSION['form_key'] = $this->formKey;
		
		//Output the form key
		echo "<input type='hidden' name='form_key' id='form_key' value='".$this->formKey."' />";
	}

	
	//Function that validated the form key POST data
	public function validate()
	{
		//We use the old formKey and not the new generated version
		if($_POST['form_key'] == $this->old_formKey)
		{
			//The key is valid, return true.
			return true;
		}
		else
		{
			//The key is invalid, return false.
			return false;
		}
	}
}
?>
Nach dem Login kopieren

结论

将此代码添加到您网站上的每个重要表单中将显着提高表单的安全性。它甚至会停止刷新问题,正如我们在步骤 4 中看到的那样。由于表单密钥仅对一个请求有效,因此不可能进行双重发布。

这是我的第一个教程,希望您喜欢它并使用它来提高您的安全性!请通过评论让我知道您的想法。有更好的方法吗?让我们知道。

进一步阅读

  • WordPress 还使用表单键(将其命名为 Nonce):Wordpress Nonce
  • 编写安全 PHP 应用程序的七个习惯
  • 在 Twitter 上关注我们,或订阅 NETTUTS RSS Feed 以获取更多日常 Web 开发教程和文章。

Das obige ist der detaillierte Inhalt vonSchützen Sie Ihre Formulare mit Formularschlüsseln. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage