Tôi cũng đang trong quá trình xây dựng hệ thống LAMP MVC từ đầu.
MVC Router Class Question
Performance
Sau khi tạo ra một kịch bản bash shell để biên dịch Apache 2.4.x từ nguồn, bạn nhận thấy rằng một Perl Tương thích thư viện Regular Expression được nướng vào quá trình này. Bất cứ lúc nào mã biểu thức chính quy phải được sử dụng, phản hồi của máy chủ http sẽ chậm hơn. Do đó, tùy chọn số một là không đi nếu hiệu suất là mối quan tâm của bạn. Có một chi phí cho các phân tích có liên quan với các biểu thức thông thường. Máy chủ web Apache đang mượn logic cho các cụm từ thông dụng. Nó không phải là Apaches home grown code.
an
Security là một vấn đề khác nhau. Thứ nhất, không có gì về việc viết lại các URL làm cho chúng an toàn. Nó là bảo mật đơn giản thông qua sự tối tăm và làm cho mọi thứ trông khá đẹp ở phía khách hàng. Theo thời gian, các lỗ hổng bảo mật được tìm thấy trong mã công cụ biểu thức chính quy. Do đó, về mặt bảo mật thực sự, bạn có thể ở trong cùng một vị trí cơ bản mà bạn không cần phải viết lại: con người hoặc bot, có thể gửi nội dung xấu đến máy chủ của bạn và bạn cần một cách để lọc và xác thực đầu vào theo cách có hệ thống. Hãy chắc chắn để lọc và xác nhận tất cả các đầu vào, đặc biệt là bất kỳ phần nào của chuỗi truy vấn được viết lại mà bạn định sử dụng.
Do đó, tùy chọn số một trình bày giao diện gọn gàng hơn (INPUT_GET
/$_GET
) để bắt đầu nhiệm vụ bảo mật của bạn. Tùy chọn số hai yêu cầu (nếu bạn đang cố gắng để được triệt để) bạn để lọc và xác nhận toàn bộ chuỗi như là một bước đầu tiên. Bước thứ hai (nói chung) sẽ là chia nhỏ và trích xuất những gì bạn mong muốn thu thập từ chuỗi lớn hơn.
Một lần nữa, bạn nên lọc và xác thực từng phần của chuỗi. Do đó, trong khi có lẽ nó dễ quản lý hơn (dễ dàng hơn, thuận tiện) để lọc/xác nhận/chia nhỏ/trích xuất/chuỗi lớn hơn trong PHP (nói, với một phương thức trong lớp bảo mật nào đó), bạn vẫn cần phải làm việc cho từng phần , cho mọi yêu cầu. Tùy chọn số một giúp bạn tiết kiệm những rắc rối của việc phải phá vỡ chuỗi lớn hơn cho chi phí thực hiện các công cụ regex trên mọi yêu cầu. Tuy nhiên, đối với hầu hết các phần, bạn chỉ có thể bắt đầu lọc và xác thực các yếu tố bạn mong muốn nhận được trong INPUT_GET
hoặc $_GET
. Tuy nhiên, một tùy chọn là chủ yếu dành cho những người thực sự hiểu cách biểu thức chính quy hoạt động và cách thức áp dụng điều này cho các URL tiềm năng mà máy chủ của bạn có thể nhận được. Nếu bạn cần nhiều hơn một RewriteRule
, nó có thể là để bạn có thể có một cái gì đó như thế này (hoặc các lý do khác) đi vào máy chủ.
index.php?0=model
index.php?0=model&1=method
index.php?0=model&1=method&2=methodArgs
Điều này giúp dễ dàng lọc và xác thực đầu vào của bạn hơn. Tuy nhiên, lưu ý rằng dòng cuối cùng ngụ ý rằng bạn vẫn có thể cần phải tách một số dòng và lọc/xác nhận thêm (nhưng điều đó có thể không xảy ra đối với mọi yêu cầu, như trong tùy chọn số 1).
Mã mẫu: Bắt tham số URL sử dụng Lựa chọn 2 (bắt đầu ở phía dưới!)
Note: Đây chỉ là một số điều cần lưu ý, không phải "là" cách để làm điều đó.
const QS_ARRAY_LIMIT = 3;
private function getPairValue($delimiter, $string)
{
return explode('$delimiter', $string)[1]; //Get the value for a pair.
}
private function isMultiValuedQueryString()
{
return (mb_strpos($this->queryStr, '&', 0, 'UTF-8') > 2);
}
private function getAllowedPairs($argsStr)
{
$pairs = explode('&', $argsStr);
$numPairs = count($pairs);
if($numPairs > self::QS_ARRAY_LIMIT)
{
throw new SecurityException("Too many query string pairs ({$numPairs}) submitted to the router.\n");
}
return $pairs;
}
private function isQueryStrPair($pair)
{
$equalPos = null;
$pairLength = mb_strlen($pair, 'UTF-8');
if($pairLength < 3)
{
throw new SecurityException("Query string pair is too short: Length: {$pairLength}!, Suspect: {$pair}\n"); //Sends to '/'
}
$equalPos = mb_strpos($pair, '=', 0, 'UTF-8');
if($equalPos === 0) //The first position.
{
throw new SecurityException("Query sting pair cannot *start* with an equal sign (=): Suspect: {$pair}\n"); //Sends to '/'
}
if($equalPos === ($pairLength - 1)) //The last position.
{
throw new SecurityException("Query sting pair cannot *end* with an equal sign (=): Suspect: {$pair}\n"); //Sends to '/'
}
return true;
}
private function getQueryStringArgs($url)
{
$delimiter = '?';
if(mb_strpos($url, $delimiter, 0, 'UTF-8') > 0)
{
return $this->getPairValue($delimiter, $url);
}
throw new RuntimeException("Malformed URL passed to query string parser.");
}
private function associateArgPairs(array $argPairs, array $values)
{
$i = 0;
foreach($argPairs as $key => &value)
{
if(isset($values[$i]))
{
$value[$key] = $values[$i];
++$i;
}
}
return $argPairs;
}
private function getQueryStrValues($url)
{
$delimiter = '=';
$argPairs = ['model' => null, 'method' => null, 'methodArgs' => null]
$inputValues = [];
// =================================================
// Valid query strings might look like (amongst many combinations):
//
// index.php?arg1=foo&agr2=bar&arg3=/baz/bang/boom
//
// Or, just one pair with no ampersand,'&'.
//
// index.php?arg1=foo
// ==================================================
// Get everything after the question mark, '?'.
$queryStringArgsStr = $this->getQueryStringArgs($url);
if($this->isMultiValuedQueryString($queryStringArgsStr)) //Check if '&' exists.
{
foreach($this->getAllowedPairs($queryStringArgsStr) as $pair)
{
if($this->isQueryStrPair($pair))
{
//Get the value for each pair., using '=' as the string delimiter.
$inputValues[] = $this->getPairValue($delimiter, $pair);
}
}
}
else
{
if($this->isQueryStrPair($queryStringArgsStr))
{
$inputValues[] = $this->getPairValue($delimiter, $queryStringArgsStr); //Get the value for each pair.
}
}
return $this->associateArgPairs($argPairs, $inputValues);
//Remember, you will still need to split up $argPairs[$methodArgs] if necessary.
//With option #1, you could start closer to this point,
//and hence filter and validate sooner.
}
Tóm tắt
Nếu bảo mật là mối quan tâm chính của bạn (có nghĩa là, giao diện của bạn vào chương trình bảo mật của bạn), nhẫn nhục chịu đựng và sử dụng tùy chọn số một. Học mod_rewrite và viết lại URL khiến bạn khá mạnh mẽ. Tại sao để lại sức mạnh trên bàn? Apache là một động vật kỳ lạ khi nói đến cấu hình nó. Nhưng, nếu bạn hiểu các URL và cụm từ thông dụng, tôi nói người đàn ông/người phụ nữ và đi cho nó. :-) Nếu tốc độ, hiểu và dễ sử dụng là mối quan tâm chính của bạn, hãy chọn tùy chọn số một. Có những người nhiệt thành muốn mọi thứ được mã hóa bằng PHP, nhưng bạn phải tự mình đánh giá những ưu và nhược điểm của cả hai tình huống.
Cập nhật: Rất tiếc. Mã này sẽ thực sự làm việc tốt hơn cho số tùy chọn 1. Trong tùy chọn số 2, 1 = blah, nơi blah sẽ là một cái gì đó như /trt/43ff/3335/f/3/fr3r/
hoặc bất cứ điều gì. Bạn sẽ không phải tìm ký hiệu và.
PHP: filter_inpur_array(), (use INPUT_GET)
PHP: Superglobals
PHP: explode()
PHP: foreach (array_expression as $key => $value)
PHP: Multibtye String Functions
những gì bạn có nghĩa là bởi an toàn? –
tốt, tôi reall chỉ giả định có những biện pháp để thực hiện để đảm bảo hệ thống của tôi/khung/etc không có bất kỳ lỗ mà tôi không biết. chỉ giả định im ngây thơ hơn tôi hy vọng – johnnietheblack
Tôi hoan nghênh những nỗ lực của bạn. –