1. Use a SQL injection cheat sheet
A basic principle is to never trust user-submitted data.
Another rule is to escape (escape) when you send or store data.
Can be summarized as: Filter input, Escape output (FIEO). Input filtering, output escaping.
The most common cause of SQL injection vulnerability is that the input is not filtered, as in the following statement:
Copy CodeThe code is as follows:
$query = "SELECT *
From users
WHERE name = ' {$_get[' name ']} ';
In this example, $_get[' name ' comes from user-submitted data that is neither escaped nor filtered ~ ~
For escape output, you need to remember that the data used outside your program needs to be escaped, otherwise it may be parsed incorrectly.
Instead, the filter input ensures that the data is correct before it is used.
For filter input, you should remember that the raw data outside your program needs to be filtered because they are untrusted.
The following examples demonstrate input filtering and output escaping:
Copy CodeThe code is as follows:
Initialize arrays for filtered and escaped data, respectively.
$clean = Array ();
$sql = Array ();
Filter the name. (For simplicity, we require alphabetic names.)
if (Ctype_alpha ($_get[' name ')) {
$clean [' name '] = $_get[' name '];
} else {
The name is invalid. Do something here.
}
Escape the name.
$sql [' name '] = mysql_real_escape_string ($clean [' name ']);
Construct the query.
$query = "SELECT *
From users
WHERE name = ' {$sql [' name ']} ';
?>
Another way to effectively prevent SQL injections is to use the prepare statement, such as:
Copy CodeThe code is as follows:
Provide the query format.
$query = $db->prepare (' SELECT *
From users
WHERE name =: Name ');
Provide the query data and execute the query.
$query->execute (Array (' name ' = = $clean [' name ']);
?>
2. Understand the difference between comparison operators
For example, you use Strpos () to detect if there is a substring in a string (such as the fruit string is not found, the function will return FALSE), and the result may result in an error:
Copy CodeThe code is as follows:
$authors = ' Chris & Sean ';
if (Strpos ($authors, ' Chris ')) {
Echo ' Chris is an author. ';
} else {
Echo ' Chris isn't an author. ';
}
?>
In the above example, because the substring is at the very beginning, the Strpos () function correctly returns 0, indicating that the substring is at the beginning of the string. Then, because the conditional statement treats the result as a Boolean (Boolean) type, 0 is computed by PHP as FALSE, resulting in a conditional statement failure.
Of course, this bug can be fixed with strict comparison statements:
Copy CodeThe code is as follows:
if (Strpos ($authors, ' Chris ')!== FALSE) {
Echo ' Chris is an author. ';
} else {
Echo ' Chris isn't an author. ';
}
?>
3. Reduce else (Shortcut the Else)
Remember that you always initialize the variables before you use them.
Consider the following conditional statement to detect whether a user is an administrator based on the user name:
Copy CodeThe code is as follows:
if (auth ($username) = = ' admin ') {
$admin = TRUE;
} else {
$admin = FALSE;
}
?>
This seems safe enough because it's easy to understand at a glance. Imagine a more complicated example, which sets the variable for name and email at the same time, for the sake of convenience:
Copy CodeThe code is as follows:
if (auth ($username) = = ' admin ') {
$name = ' Administrator ';
$email = ' admin@example.org ';
$admin = TRUE;
} else {
/* Get the name and email from the database. */
$query = $db->prepare (' SELECT name ', email
From users
WHERE username =: username ');
$query->execute (Array (' username ' = $clean [' username ')];
$result = $query->fetch (PDO::FETCH_ASSOC);
$name = $result [' name '];
$email = $result [' email '];
$admin = FALSE;
}
?>
Because $admin is explicitly set to TRUE or FALSE, everything seems to be intact. However, if another developer later added a ElseIf statement to the code, chances are that he will forget it:
Copy CodeThe code is as follows:
if (auth ($username) = = ' admin ') {
$name = ' Administrator ';
$email = ' admin@example.org ';
$admin = TRUE;
} elseif (auth ($username) = = ' MoD ') {
$name = ' Moderator ';
$email = ' mod@example.org ';
$moderator = TRUE;
} else {
/* Get the name and email. */
$query = $db->prepare (' SELECT name ', email
From users
WHERE username =: username ');
$query->execute (Array (' username ' = $clean [' username ')];
$result = $query->fetch (PDO::FETCH_ASSOC);
$name = $result [' name '];
$email = $result [' email '];
$admin = FALSE;
$moderator = FALSE;
}
?>
If a user provides a user name (username) that can trigger the ElseIf condition, the $admin is not initialized, which can lead to unnecessary behavior, or worse, a security vulnerability. In addition, a similar situation exists for the $moderator variable, which is not initialized in the first condition.
By initializing the $admin and $moderator, it is quite easy to avoid the occurrence of this situation:
Copy CodeThe code is as follows:
$admin = FALSE;
$moderator = FALSE;
if (auth ($username) = = ' admin ') {
$name = ' Administrator ';
$email = ' admin@example.org ';
$admin = TRUE;
} elseif (auth ($username) = = ' MoD ') {
$name = ' Moderator ';
$email = ' mod@example.org ';
$moderator = TRUE;
} else {
/* Get the name and email. */
$query = $db->prepare (' SELECT name ', email
From users
WHERE username =: username ');
$query->execute (Array (' username ' = $clean [' username ')];
$result = $query->fetch (PDO::FETCH_ASSOC);
$name = $result [' name '];
$email = $result [' email '];
}
?>
No matter what the rest of the code is, it is now clear that the $admin value is false unless it is explicitly set to a different value. The same is true for $moderator. The worst possible scenario is that $admin or $moderator are not modified under any conditions, causing someone who is administrator or moderator not to be treated as a corresponding administrator or moderator.
If you want to shortcut something, and you see that our example has included the else feel a little disappointed. We have a bonus tip you might be interested in. We are not sure that it can be considered a shortcut, but we hope it will still be helpful.
Consider a function that detects whether a user is authorized to view a specific page:
Copy CodeThe code is as follows:
function authorized ($username, $page) {
if (!isblacklisted ($username)) {
if (ISAdmin ($username)) {
return TRUE;
} elseif (Isallowed ($username, $page)) {
return TRUE;
} else {
return FALSE;
}
} else {
return FALSE;
}
}
?>
This example is quite simple, because only three rules need to be considered:
Administrators is always allowed access,
The blacklist is always forbidden to visit,
Isallowed () Determines whether other persons have access.
(There is one other exception: When a Administrator is blacklisted, but it seems unlikely, so we ignore it directly here.)
We use functions to make this judgment to keep the code simple and focus on the business logic.
Such as:
Copy CodeThe code is as follows:
function authorized ($username, $page) {
if (!isblacklisted ($username)) {
if (ISAdmin ($username) | | isallowed ($username, $page)) {
return TRUE;
} else {
return FALSE;
}
} else {
return FALSE;
}
}
?>
In fact, you can fine-subtract the entire function into a compound condition:
Copy CodeThe code is as follows:
function authorized ($username, $page) {
if (!isblacklisted ($username) && (ISAdmin ($username) | | isallowed ($username, $page)) {
return TRUE;
} else {
return FALSE;
}
}
?>
Finally, this can be reduced to just one return:
Copy CodeThe code is as follows:
function authorized ($username, $page) {
Return (!isblacklisted ($username) && (ISAdmin ($username) | | isallowed ($username, $page));
}
?>
If your goal is to tentatively the number of lines of code, then that's what you do. However, you should note that we are using isblacklisted (), ISAdmin () and isallowed (), depending on what is involved in these judgments, reducing the code to only one compound condition may not be attractive.
So, speaking of our little tricks, an "immediate return" function, so if you return as soon as possible, you can simply express these rules:
Copy CodeThe code is as follows:
function authorized ($username, $page) {
if (isblacklisted ($username)) {
return FALSE;
}
if (ISAdmin ($username)) {
return TRUE;
}
Return isallowed ($username, $page);
}
?>
This example uses more lines of code, but it is very simple and not noticeable. More importantly, this method reduces the number of contexts that you must consider. For example, once you've decided whether a user is blacklisted, you can safely forget about it. Especially when your logic is complicated, it's quite helpful.
4. Always use curly braces
PS: Forgiveness is "throw out those square brackets drop those Brackets"
According to the contents of this article, our corresponding author should mean "braces," not brackets. "Curly brackets" may mean curly braces, but "brackets" usually means "square brackets". This technique should be ignored unconditionally because, without curly braces, readability and maintainability are broken.
To give a simple example:
Copy CodeThe code is as follows:
if (date (' d M ') = = ' May ')
$birthdays = Array (' Al Franken ',
' Chris Shiflett ',
' Chris Wallace ',
' Lawrence Tureaud ');
?>
If You're good enough, smart enough, secure enough, notorious enough, or pitied enough, you might want to join a social gathering on May 21:
Copy CodeThe code is as follows:
if (date (' d M ') = = ' May ')
$birthdays = Array (' Al Franken ',
' Chris Shiflett ',
' Chris Wallace ',
' Lawrence Tureaud ');
Party (TRUE);
?>
Without curly braces, this simple condition causes you to go to social gatherings every day. Maybe you have perseverance, so this error is a popular one. I hope that stupid example doesn't distract from the idea that over-partying is an unexpected side effect.
In order to advocate throwing out curly braces, the previous article used a short statement like the following as an example:
Copy CodeThe code is as follows:
if ($gollum = = ' halfling ') $height-;
else $height + +;
?>
Because each condition is placed on a separate line, this error seems to occur less, but this leads to another problem: inconsistent code and the need for more time to read and understand. Consistency is such an important feature that developers often follow a coding standard, even if they don't like the coding standards themselves.
We advocate always using curly braces:
Copy CodeThe code is as follows:
if (date (' d M ') = = ' May ') {
$birthdays = Array (' Al Franken ',
' Chris Shiflett ',
' Chris Wallace ',
' Lawrence Tureaud ');
Party (TRUE);
}
?>
It's okay for you to have a party every day, but make sure it's thought through, and, please, be sure to invite us!
5. Try to use Str_replace () instead of ereg_replace () and Preg_replace ()
We hate to hear the denial, but this little trick of demonstrating misuse leads to the same abuse that it tries to avoid. (
We hate to sound disparaging, but this tip demonstrates the sort of misunderstanding that leads to the same misuse it ' s TR Ying to prevent.)
It is clear that string functions are faster and more efficient than regular expression functions in character matching, but the author is badly trying to derive a corollary from failure:
(FIX me:it ' an obvious truth that string functions is faster at string matching than regular expression functions, but The author ' s attempt to draw a corollary from this fails miserably:)
If you ' re using the regular expressions, then ereg_replace () and Preg_replace () would be much faster than str_replace ().
Because Str_replace () does not support pattern matching, this statement makes no sense. The choice between string functions and regular expression functions comes down to which are fit for purpose, not which is Faster. If you need to match a pattern, use a regular expression function. If you need the match a string, use a string function.
6. Using the triple operator
The benefits of ternary operators are worth discussing. Here is a line from the code of the most recent audits we have taken:
Copy CodeThe code is as follows:
$host = strlen ($host) > 0? $host: Htmlentities ($host);
?>
Ah, the true intention of the author is to escape $host if the length of the string is greater than 0, but unexpectedly does the opposite thing. It's easy to make a mistake, isn't it? Well, maybe. Is it easy to miss during the code audit? Of course. Brevity does not necessarily make the code very good.
Triple operators are good for single-line, prototype, and template, but we believe that a normal conditional statement is always better. PHP is descriptive and detailed, and we think the code should also be.
7. Memcached
Disk access is slow, network access is slow, and the database typically uses both.
The memory is very fast. Using local cache avoids the overhead of network and disk access. Combining these truths, then, you think of Memcached, a "Distributed memory object caching system," originally developed for the Perl-based blogging platform LiveJournal.
If your program is not distributed across multiple servers, you may not need to memcached. Single-cache method-serializes the data and then saves it in a temporary file. For example – a lot of extra work can be eliminated for each request. In fact, this is the type of low hanging fruit that we consider to help our customers optimize their applications.
What is low-hanging fruit:
A fruit-bearing tree often contains some branches low enough for animals and humans to reach without much effort. The fruit contained on these lower branches could be isn't being as ripe or attractive as the fruit on higher limbs, but it's US ually more abundant and easier to harvest. From this we get the popular expression ' low hanging fruit ', which generally means selecting the easiest targets with the least amount of effort.
One of the simplest and most common ways to cache data in memory is to use the shared Type helper method in APC, a caching system originally developed by our colleague George Schlossnagle, considering the following example:
Copy CodeThe code is as follows:
$feed = Apc_fetch (' News ');
if ($feed = = = FALSE) {
$feed = file_get_contents (' Http://example.org/news.xml ');
Store this data in the shared memory for five minutes.
Apc_store (' News ', $feed, 300);
}
Do something with $feed.
?>
With this type of cache, you don't have to wait for the remote server to send feed data every time you request it. Some delays have been generated – in this case the upper limit is five minutes, but can be adjusted to near real-time depending on your application needs.
8. Using Frames
All decisions will have results, we like the framework-in fact, CakePHP and Solar's main developers are working with us in Omniti-but using a framework doesn't magically make things better for you.
In October, our colleague Paul Jones wrote an article for HP Advent, called the framework as franchise, in which he compared the framework to the commercial franchise. He cites Michael Gerber's advice in the book "Electronic Myth Reproduction" ("The E-myth Revisited"):
Gerber points out that running a successful business, entrepreneurs need to act as if he were going to sell his business as a prototype of a franchise. This is the only way for an enterprise owner to be able to participate in each decision without being personally involved in the operation.
(Gerber notes that to run a successful business, the entrepreneur needs to act as if he's going to sell his business as A franchise prototype. It's the only-to-do business owner can make the business operate without him being personally involved in every Decisio N.)
This is a good suggestion. Whether you're planning to use a framework or define your own tags and conventions, it's important to look at value from a future developer perspective.
Although we are happy to give you a universal truth, extending the idea to show that a framework is always appropriate is not something we want to do.
If you ask us if we should use a framework, the best answer we can give is, "it depends." ”
9. Correct use of the error suppression operator
Always try to avoid using the error suppression action symbol. In the previous article, the author shows:
The @ operator is quite slow and if you need to write high-performance code it can make a lot of overhead.
Error suppression is slow because PHP dynamically changes the error_reporting level to 0 before executing the suppression statement, and then immediately restores it. This is going to cost.
Worse, using the error suppressor makes it difficult to trace the root cause of the problem.
The previous article used the following example to support the practice of assigning values to a variable by reference ... (How do you translate this sentence?) I faint ~ ~ ~)
The previous article uses the following example to support the practice of assigning a variable by reference when it was UN Known if $albus is set:
Copy CodeThe code is as follows:
$albert =& $albus;
?>
Although this is working-for now-depending on strange, undefined behavior, a good understanding of why it works is a good way to generate bugs.
Because the $albert is quoted $albus, later changes to $albus will also affect $albert.
A better solution is to use Isset (), plus curly braces:
Copy CodeThe code is as follows:
if (!isset ($albus)) {
$albert = NULL;
}
?>
The effect of assigning null to $albert and assigning a nonexistent reference to it is the same, but more explicit, greatly improving the clarity of the code and avoiding the referential relationship between the two variables.
If you inherit code that uses the error suppression operator excessively, we've got a bonus tip for you. There is a new PECL extension called Scream that disables error suppression.
10. Use Isset () instead of strlen ()
This is actually an ingenious method, although the previous article does not explain this at all. The following are examples of additions:
Copy CodeThe code is as follows:
if (Isset ($username [5])) {
The username is at least six characters long.
}
?>
When you treat a string as an array (wilderness without lights: In fact, in C, characters usually exist as arrays), and every character in a string is an element of an array. By detecting the presence or absence of a particular element, you can detect whether the string is at least as many characters present. (Note that the first character is element 0, so $username [5] is the 6th character in the $username. )
The reason for using isset slightly faster than strlen is complicated. The simple explanation is that strlen () is a function, and isset () is a grammatical structure. Generally speaking,
Calling a function is more expensive than using a language structure.
About the Author:
Hi, we are Chris Shiflett and Sean Coates. We are all in Omniti ("The most important web company you ve never heard of") work, blog about PHP and other stuff at shiflett.org and seancoates.com, curate PHP Advent, and do the Twitter thing as @shiflett and @coates.
Translation from:http://coding.smashingmagazine.com/2009/03/24/10-useful-php-tips-revisited/
http://www.bkjia.com/PHPjc/324064.html www.bkjia.com true http://www.bkjia.com/PHPjc/324064.html techarticle 1. Using a SQL injection cheat sheet A basic principle is to never trust the data submitted by users. Another rule is to escape (...) when you send or store data .