2011-08-21 6 views
3

HTML Purifier 또는 CSRF Magic과 같은 기능이 실제로 HTTP 요청을 차단합니까? 그 문서는 Python의 Django Middleware 프레임 워크에 대한 아이디어를 기반으로하지만, 아직 HTTP 요청을 가로채는 방법에 대한 문서를 아직 찾지 못했습니다. PHP 확장을 설치할 필요없이 실제로 작동합니다.HTML 정수기에 의한 요청 차단

누구든지 문제에 관해 밝힐 수 있습니까?

감사

답변

1

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은 숨겨진 입력을 추가하도록 스크립트의 원래 출력을 수정 한 다음 그 결과를 인쇄합니다.

+0

'$ GLOBALS [ 'csrf'] [ 'rewrite']'[what ... 코드] (http://www.bigbible.org/blog/uploaded_images/242640415_46bf42b3a7-784053.jpg) –

+0

xP – Matchu

-1

농담이 없으면 - "차단"HTTP 요청 및 응답은 모든 웹 응용 프로그램이 모두해야 할 일이다 보낼 수 있습니다.
PHP는 웹 응용 프로그램을 만들기위한 도구로 설계 되었기 때문에 확장이 필요하지 않습니다.
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; 
    } 
} 
+0

이것은 표준 방식으로 요청을 처리하기위한 하나의 프레임 워크가 될 수 있지만 맨 위에있는 CSRF Magic 스크립트가 자동으로 스크립트의 출력을 다시 작성하여 보내기 만하면되는 것 같습니다. – Matchu

+0

@Matchu 당신은 응답이 아니라 요청에 대해 말하고 있습니다. –

+1

당신은 질문에 전혀 관련이 없습니다. Lemme은 간단히 설명 할 수 있습니다. "CSRF Magic과 같은 스크립트가 내 요청을 가로 챌 때 어떻게하면 맨 위에 포함 했습니까?" 이 클래스의 유용성은 우리가 논의하고있는보다 구체적인 경우와는 관련이없는 것처럼 보입니다. "요청을 어떻게 가로 챌 수 있습니까?" 그것은 "어떻게 * 요청을 차단합니까?"입니다. – Matchu