Can I use htmlentities() in an SQL query?

非 Y 不嫁゛ 提交于 2019-12-07 17:29:33

问题


Much thanks for the discussion my original question generated. I took Jay's suggestion to use bind_param(), but there is something I don't understand about it that may be giving me the Server Error: "The website encountered an error while retrieving...". I don't know what the parameter 'sssd' that came with the example means.

Any suggestions as to what is generating the Server Error are much appreciated.

<?php

$mysqli = new mysqli('my-database-address', 'my-username', 'my-password', 'my-database-name');
f (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit(); }

$stmt = $mysqli->prepare("INSERT INTO volunteers VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param('sssd', $first_name, $last_name, $street_address, $apt_unit, $city, $zip, 
$email, $phone, $planning, $signatures, $canvassing, $phone_bank, $media, $press_releases,
$volunteer_coordinator, $speaker, $house_parties, $web_page, $other, $skills, $organizations);

$first_name = '$_POST[first_name]'; $last_name = '$_POST[last_name]'; $street_address = '$_POST[street_address]';
$apt_unit = '$_POST[apt_unit]'; $city = '$_POST[city]'; $zip = '$_POST[zip]'; $email = '$_POST[email]';
$phone = '$_POST[phone]'; $planning = '$_POST[planning]'; $signatures = '$_POST[signatures]'; 
$canvassing = '$_POST[canvassing]'; $phone_bank = '$_POST[phone_bank]'; $media = '$_POST[media]'; 
$press_releases = '$_POST[press_releases]'; $volunteer_coordinator = '$_POST[volunteer_coordinator]'; 
$speaker = '$_POST[speaker]'; $house_parties = '$_POST[house_parties]'; $web_page = '$_POST[web_page]'; 
$other = '$_POST[other]'; $skills = '$_POST[skills]'; $organizations = '$_POST[organizations]';

$stmt->execute();
$stmt->close();

echo "<br /><br />";
echo "<div class='center-col-wrap'>";
echo "Your information has been received.";
echo "<br /><br />";
echo "Thank you for volunteering!"; echo "<br />";
echo "Your help in this effort to bring greater democracy to Oakland"; echo "<br />";
echo "will go a long way to create a healthy and informed community."; echo "<br />";
echo "<br /><br />";
echo "<a href='http://communitydemocracyproject.org/'>Return to CDP Home Page.</a>";
echo "</div>";

$mysqli->close();
?>

MY ORIGINAL QUESTION IS BELOW:

I didn't know if this would work or not. It does not So how can I use htmlentities() here?

Any help is much appreciated.

$sql="INSERT INTO volunteers (first_name, last_name, street_address, apt_unit, city, zip, email, phone,
planning, signatures, canvassing, phone_bank, media, press_releases, volunteer_coordinator, speaker, 
house_parties, web_page, other, skills, organizations)
VALUES
('htmlentities($_POST[first_name])','htmlentities($_POST[last_name])','htmlentities($_POST[street_address])',
'htmlentities($_POST[apt_unit])','htmlentities($_POST[city])','htmlentities($_POST[zip])',
'htmlentities($_POST[email])','htmlentities($_POST[phone])','$_POST[planning]','$_POST[signatures]','$_POST[canvassing]','$_POST[phone_bank]',
'$_POST[media]','$_POST[press_releases]','$_POST[volunteer_coordinator]','$_POST[speaker]',
'$_POST[house_parties]','$_POST[web_page]','$_POST[other]','htmlentities($_POST[skills])','htmlentities($_POST[organizations])')";

回答1:


As Theodore said, never use htmlentities() for "escaping" something you want to put in your DB.

I strongly recommend to use prepared statements when anything that (could) come from outside (the user) is stored in a database.

Prepared statements are really easy to use.

If you use PDO to access you database help can be found here. As you can see the bindParam() method is used to assign any value to a placeholder in the query.

If you use mysqli you can find the docs here. The syntax of bind_param() is slightly different since the placeholders don't have names (order matters) and first argument is a string that determines what type the arguments have ("s" for string, "i" for integer and so on).

Using prepared statements has several positive effects. First of all it automatically masks the data that is provided in the bindParam()/bind_param() method and is the best way to close the SQL injection attack vector and it even optimizes the performance of your queries by storing the execution plan in the database (this has a little overhead but if you execute a query twice it pays off double).

PS: htmlentities() should only be used if you want to display some HTML as raw text to your users (code listings for instance).

PPS: Don't use real_escape_string() to prevent SQL injection since it's not safe (supeskt.org)

Update

First of all, for a follow up you should ask a new question. People don't read questions that are already marked as answered and by opening new questions you give kind people an opportunity to get some reward. :)

Nevertheless, the first argument "sssd" tells the database provider that you are passing four arguments, three of type string and a fourth of type double (in the example in the docs three strings and one double are bound ("DEU", "Bavarian", "F" and 11.2)). This is obviously not the case here, you are actually passing (binding) 21 values.

Depending of the type that the columns in your volunteers table have you need to pass a string of 21 characters as the first argument. There are four possible chars that can be used to determine the type:

  • i for integer
  • d for double (floating point numbers)
  • s for string
  • b for boolean

All you have to do is to check what types you DB columns have. You will see that the types in the database have different names (like varchar, float etc.). If you google for this names you will find out that they are similar to string, integer, double and boolean. So you have to choose the best matching type depending on the column type (string ≆ varchar, double ≆ float, string ≆ tinytext, string ≆ date/datetime etc. pp.) and you should ensure that the values (your $_POST variables) actually match the type you defined.

Assuming that all your columns are of an text like type like varchar, the first argument would look like 'sssssssssssssssssssss' (21 times s) or 'ssssssssssssssissssss' if the column that takes the volunteer_cordinator is of type int (just for instance).

After you have done this you should double check if f (mysqli_connect_errno()) is a copy&paste related mistake or if you have actually missed the i in your code (should be if (mysqli_connect_errno())).

If you have checked that you should consider to write $_POST['xyz'] instead of '$_POST[xyz]', it will help you, really (' marks the start/end of a string and xyz is in fact the string here).

If you still encounter errors enable more detailed error information by adding error_reporting(E_ALL); at the top of your file (you should remove this for security reasons when your site goes live) and ask a new question.

Update 2

Double check your MySQL connection string (the arguments you pass in the mysql() method). Are you sure that your password starts with an @ and ends with a full stop? By the way, you shouldn't post passwords etc. in the public.

Ensure that you server supports the mysqli methods by running a script containing only

<?php
// Show all information, defaults to INFO_ALL
phpinfo();
?>

and check the output for something like this:




回答2:


You never want to use htmlentities() on data that's going to be inserted into the database!

NEVER!

Only use it when you are outputting data to a web page.

Otherwise, if you ever want to do anything with that data, ever, that's not directly to a web browser (think, sending emails, or counting words, or outputting to CSV, what have you), you'll quickly realize your error.




回答3:


To answer your question exactly as you wanted, you'll need to exit out of your string:

$sql="INSERT INTO volunteers (...) VALUES    
('".htmlentities($_POST['first_name'])."','".htmlentities($_POST['last_name'])'." ...

(But please, as Theodore clearly says, don't do this. It's bad. Really, don't do it. Please!)

I think you're trying to escape your input/output. The best way to do is is firstly to stop SQL injection, use your favourite DB escaping method. I'm just using this as an example, you might have a better setup than this short example code:

$sql="INSERT INTO volunteers (...) VALUES    
('".$mysqli->real_escape_string($_POST['first_name'])."','".$mysqli->real_escape_string($_POST['last_name'])'." ...

And then when you output, escape using htmlentities:

echo htmlentities($output->first_name);


来源:https://stackoverflow.com/questions/9136979/can-i-use-htmlentities-in-an-sql-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!