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