HTML Purifier或CSRF Magic如何攔截HTTP請求?它的文檔說它基於Django中間件Python框架的想法,但我還沒有找到一些關於如何攔截HTTP請求的文檔。它的工作原理並不需要安裝任何PHP擴展。HTML淨化器攔截請求
任何人都可以解釋一下這個問題?
問候
HTML Purifier或CSRF Magic如何攔截HTTP請求?它的文檔說它基於Django中間件Python框架的想法,但我還沒有找到一些關於如何攔截HTTP請求的文檔。它的工作原理並不需要安裝任何PHP擴展。HTML淨化器攔截請求
任何人都可以解釋一下這個問題?
問候
CSRF Magic使用PHP的output control函數。它捕獲腳本的輸出,修改它,並使用特殊的處理函數修改它在打印之前捕獲的輸出。所以,真正的魔力在於ob_start
。如果你有興趣,請閱讀它。此外,由於CSRF Magic是一個開源項目,您可以read the script itself for more detailed information。
它最終歸結爲line 371:
if ($GLOBALS['csrf']['rewrite']) ob_start('csrf_ob_handler');
該行表示,如果條件爲真(它通常是這樣),當輸出完成後啓動輸出緩衝(ob_start
)和, ,在該輸出上運行csrf_ob_handler
。 csrf_ob_handler
修改腳本的原始輸出以添加隱藏的輸入,然後輸出結果。
如果沒有笑話 - 「攔截」 HTTP請求和響應發送什麼是任何Web應用程序應該做的。
而且您不需要任何擴展,因爲PHP的設計正好是創建Web應用程序的工具。
要讀取HTTP請求的數據,請使用數組$ _GET,$ _POST,$ _SERVER(有時需要php://input
),併發送響應,您可以僅使用echo "that's my response!";
。
我甚至可以給你我的兩個班,請求和響應工作,希望這將是有用的(或只是有趣,至少):
<?php
namespace Jamm\HTTP;
class Request
{
protected $method;
protected $headers;
protected $data;
protected $accept;
const method_GET = 'GET';
const method_POST = 'POST';
const method_PUT = 'PUT';
const method_DELETE = 'DELETE';
/**
* @param bool $parse - parse current input to object's variables (input request)
* @return \Jamm\HTTP\Request
*
*/
public function __construct($parse = false)
{
$this->method = self::method_GET;
if ($parse) $this->BuildFromInput();
$this->setHeader('Content-type', 'text/plain');
}
public function BuildFromInput()
{
$this->headers = $_SERVER;
$this->accept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : '';
$this->method = $_SERVER['REQUEST_METHOD'];
switch ($this->method)
{
case 'HEAD':
case 'GET':
$this->data = $_GET;
break;
case 'POST':
$this->data = $_POST;
break;
default:
parse_str(file_get_contents('php://input'), $this->data);
}
}
/**
* Return header from array by key, or all keys
* @param string $key
* @return null|array|mixed
*/
public function getHeaders($key = null)
{
if (!empty($key))
{
return isset($this->headers[$key]) ? $this->headers[$key] : NULL;
}
else return $this->headers;
}
/**
* Get type of request method
* @return string
*/
public function getMethod()
{
return $this->method;
}
/**
* Return key or all the keys of request
* @param string $key
* @return null|array|string|numeric
*/
public function getData($key = null)
{
if (empty($key)) return $this->data;
else
{
return isset($this->data[$key]) ? $this->data[$key] : NULL;
}
}
/**
* Return HTTP_ACCEPT header
* @return string
*/
public function getAccept()
{
return $this->accept;
}
/**
* Check, if this type is acceptable
* @param string $type
* @return bool
*/
public function isAcceptable($type)
{
if (empty($type) || (stripos($this->getAccept(), $type)!==false)) return true;
return false;
}
public function setHeader($header, $value)
{
$this->headers[$header] = $value;
}
/**
* Set the request method
* @param $method
* @return void
*/
public function setMethod($method)
{
$this->method = strtoupper($method);
if ($this->method!=self::method_GET) $this->setHeader('Content-type', 'application/x-www-form-urlencoded');
}
public function setDataKey($key, $value)
{
$this->data[$key] = $value;
}
public function SetAccept($accept)
{
$this->accept = $accept;
}
/**
* Send request by URL. Pass $Response argument, if you need response
* @param $URL
* @param IResponse|null $Response
* @return bool|IResponse
*/
public function Send($URL, IResponse $Response = NULL)
{
$url_data = parse_url($URL);
$fp = fsockopen($url_data['host'], 80);
if (!$fp) return false;
$path = (isset($url_data['path']) ? $url_data['path'] : '/').
(isset($url_data['query']) ? '?'.$url_data['query'] : '');
$data = $this->getData();
if (!empty($data) && is_array($data)) $data = http_build_query($data);
if ($this->method==self::method_GET)
{
fwrite($fp, $this->method." $path?$data HTTP/1.0\r\n");
}
else
{
fwrite($fp, $this->method." $path HTTP/1.0\r\n");
fwrite($fp, "Content-Length: ".strlen($data)."\r\n");
}
fwrite($fp, "Host: {$url_data['host']}\r\n");
foreach ($this->getHeaders() as $header_name => $header_value)
{
fwrite($fp, "$header_name: $header_value\r\n");
}
fwrite($fp, "Connection: Close\r\n\r\n");
if ($this->method!=self::method_GET)
{
fwrite($fp, $data);
}
if (!empty($Response)) return $this->ReadResponse($fp, $Response);
else return true;
}
/**
* @param \resource $fresource
* @param IResponse $response
* @return IResponse
*/
protected function ReadResponse($fresource, IResponse $response)
{
//read headers
$status_header = '';
$headers = array();
while (!feof($fresource))
{
$header = trim(fgets($fresource));
if (!empty($header))
{
if (empty($status_header)) $status_header = $header;
if (strpos($header, ':')!==false)
{
$header = explode(':', $header);
$headers[trim($header[0])] = trim($header[1]);
}
else $headers[] = $header;
}
else break;
}
$response->setHeaders($headers);
if (!empty($status_header))
{
$status_header = explode(' ', $status_header);
$response->setStatusCode(intval(trim($status_header[1])));
}
//read body
$body = '';
while (!feof($fresource)) $body .= fread($fresource, 4096);
fclose($fresource);
if (!empty($body)) $response->setBody($body);
return $response;
}
/**
* Set array of data
* @param array $values
*/
public function setData(array $values)
{
$this->data = $values;
}
}
和響應:
<?php
namespace Jamm\HTTP;
class Response implements IResponse
{
protected $status_code;
protected $body;
protected $headers;
protected $serialize_method;
const serialize_JSON = 'JSON';
const serialize_XML = 'XML';
const serialize_PHP = 'PHP';
const header_Serialized = 'API-Serialized';
public function __construct($body = '', $status_code = 200)
{
$this->body = $body;
$this->status_code = $status_code;
$this->serialize_method = self::serialize_JSON;
}
public function getStatusCode()
{
return $this->status_code;
}
/** @param int $status_code */
public function setStatusCode($status_code)
{
$this->status_code = (int)$status_code;
}
/**
* Set header for the response
* @param string $header
* @param string|numeric $value
*/
public function setHeader($header, $value)
{
$this->headers[$header] = $value;
if ($header==='Location' && $this->status_code==200) $this->setStatusCode(301);
}
public function getHeader($header)
{
return isset($this->headers[$header]) ? $this->headers[$header] : NULL;
}
/**
* Get body of the response
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* Get Result of response - unpack value of body and headers
* @return bool|mixed
*/
public function getResult()
{
if ($this->getStatusCode() >= 400) return false;
if (($serialization_method = $this->getHeader(self::header_Serialized)))
{
$this->serialize_method = $serialization_method;
return $this->unserialize($this->body);
}
else return $this->body;
}
/**
* Set body of the response
* @param $body
*/
public function setBody($body)
{
if (!is_scalar($body))
{
$this->body = $this->serialize($body);
$this->setHeader(self::header_Serialized, $this->serialize_method);
}
else $this->body = $body;
}
public function getHeaders()
{
return $this->headers;
}
public function setHeaders(array $headers)
{
$this->headers = $headers;
}
public function serialize($content)
{
switch ($this->serialize_method)
{
case self::serialize_JSON:
return json_encode($content);
default:
return serialize($content);
}
}
public function unserialize($content)
{
switch ($this->serialize_method)
{
case self::serialize_JSON:
return json_decode($content, true);
default:
return unserialize($content);
}
}
/**
* Send headers and body to output
*/
public function Send()
{
$headers = $this->getHeaders();
if (!empty($headers))
{
foreach ($headers as $header_key => $header_value)
{
header($header_key.': '.$header_value, true, $this->status_code);
}
}
print $this->body;
}
}
'$ GLOBALS ['csrf'] ['rewrite']'[什麼是...代碼](http://www.bigbible.org/blog/uploaded_images/242640415_46bf42b3a7-784053.jpg) –
無論如何,這是行XP – Matchu