Download Ajax and DB

Document related concepts

Microsoft Access wikipedia , lookup

Oracle Database wikipedia , lookup

Extensible Storage Engine wikipedia , lookup

Entity–attribute–value model wikipedia , lookup

Relational algebra wikipedia , lookup

Concurrency control wikipedia , lookup

Database wikipedia , lookup

Ingres (database) wikipedia , lookup

Microsoft Jet Database Engine wikipedia , lookup

Microsoft SQL Server wikipedia , lookup

Open Database Connectivity wikipedia , lookup

SQL wikipedia , lookup

Versant Object Database wikipedia , lookup

Clusterpoint wikipedia , lookup

PL/SQL wikipedia , lookup

Database model wikipedia , lookup

Relational model wikipedia , lookup

Transcript
AJAX-2
Integrating Javascript, AJAX, PHP and
MySQL
CS346
1
Integrating AJAX, PHP and MySQL




Ex4_1.php grabs a random entry from DB and
displays it in an empty field(div)
Disables the slot if already filled.
Clicking a field in Ex4_1.php calls JS function
grabword
Grabword runs AJAX


to retrieve a random item from DB and display it in the field
or
disable the field if filled
CS346
2
<?php /* ex4_1.php */ ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example 4_1</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="text/javascript" src="functions.js"></script>
</head>
<body>
<?php
for ($i = 1; $i < 9; $i++){
?>
<div class="dborder" id=<?php echo "dborder$i"; ?>
onclick="grabword (this.id)"></div>
<?php
}
?>
</body>
</html>
CS346
3
Notable items in ex4_1.php


PHP tags with a for statement set up a table
with 8 elements, each with a different name
onclick event used to fire AJAX


To grab a word from DB table block randomly
Populate the word into the element clicked


Each element is in a div tag with an id
this.id identifies the element clicked.
CS346
4
From MySQL Console
mysql> show databases;
+--------------------+
| Database
|
+--------------------+
| information_schema |
| books
|
| cs346
|
| mailinglist
|
| mysql
|
| products
|
| testdb1
|
+--------------------+
7 rows in set (0.14 sec)
5
Create a database in WAMP
On cs346, no need to create a database. Just use
the one created for you.
mysql> create database ex04a;
Query OK, 1 row affected (0.08 sec)
mysql> show databases;
+--------------------+
| Database
|
+--------------------+
| information_schema |
| books
|
| cs346
|
| ex04a
|
| mailinglist
|
| mysql
|
| products
|
| testdb1
|
+--------------------+
8 rows in set (0.02 sec)
6
Create a table called block in database
ex04a
mysql> use ex04a;
Database changed
mysql> create table block (
-> blockid int NOT NULL PRIMARY KEY,
-> content varchar(20)
-> );
Query OK, 0 rows affected (0.27 sec)
mysql> show tables;
+-----------------+
| Tables_in_ex04a |
+-----------------+
| block
|
+-----------------+
1 row in set (0.00 sec)
7
Check the schema
mysql> describe block;
+---------+-------------+------+-----+---------+-------+
| Field
| Type
| Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| blockid | int(11)
| NO
| PRI | NULL
|
|
| content | varchar(20) | YES |
| NULL
|
|
+---------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
8
mysql> insert into block values (1, 'frying');
Query OK, 1 row affected (0.02 sec)
mysql> insert into block values (2, 'awaits');
Query OK, 1 row affected (0.00 sec)
mysql> insert into block values (3, 'similar');
Query OK, 1 row affected (0.00 sec)
INSERT
the
entries
mysql> insert into block values (4, 'invade');
Query OK, 1 row affected (0.00 sec)
mysql> insert into block values (5, 'profiles');
Query OK, 1 row affected (0.02 sec)
mysql> insert into block values (6, 'clothes');
Query OK, 1 row affected (0.00 sec)
mysql> insert into block values (7, 'riding');
Query OK, 1 row affected (0.00 sec)
mysql> insert into block values (8, 'postpone');
Query OK, 1 row affected (0.00 sec)
9
Query the table with a SELECT
statement
mysql> select * from block;
+---------+----------+
| blockid | content |
+---------+----------+
|
1 | frying
|
|
2 | awaits
|
|
3 | similar |
|
4 | invade
|
|
5 | profiles |
|
6 | clothes |
|
7 | riding
|
|
8 | postpone |
+---------+----------+
8 rows in set (0.00 sec)
10
Sequence of events





Ex4_1.php displays 8 fields
On clicking any field, grabword() in functions.js is
called
If field is empty, run AJAX call to
wordgrabber.php to fill it, otherwise blank the
field
wordgrabber.php queries the database
$querystr = "SELECT content FROM block
ORDER BY RAND() LIMIT 1";
11
Running ex4_1.php
12
Ex4_1.php
onclick
Javascript
function
grabword(id)
Ajax
wordgrabber.php
dbconnector.php
include dbconnector.php
define connection variables
call opendatabase()
function opendatabase()
CS346
13
JavaScript function grabword(element_id)


grabword accepts the current object’s id
grabword function is in an external JavaScript
file


An XMLHttpRequest object xmlhttp has been
created
Run an Ajax request to


either populate an empty box
Or make the box empty if already populated
CS346
14
function grabword (theelement){
//If there is nothing in the box, run AJAX to populate it.
if (document.getElementById(theelement).innerHTML.length == 0) {
//Change the background color.
document.getElementById(theelement).style.background = "#CCCCCC";
serverPage = "wordgrabber.php";
var obj = document.getElementById(theelement);
xmlhttp.open("POST", serverPage);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
obj.innerHTML = xmlhttp.responseText;
}
}
xmlhttp.send(null);
} else {
//Change the background color.
document.getElementById(theelement).style.background = "#FFFFFF";
//If the box is already populated, clear it.
document.getElementById(theelement).innerHTML = "";
}
}
CS346
15
<?php
// wordgrabber.php
// Require in the database connection.
require_once ("dbconnector.php");
// Open the database.
$db = opendatabase();
// Then perform a query to grab a random word from DB table block
// ORDER BY RAND() combined with LIMIT to select a random sample
// from a set of rows:
$querystr = "SELECT content FROM block ORDER BY RAND() LIMIT 1";
if ($myquery = mysql_query ($querystr)) {
$mydata = mysql_fetch_array ($myquery);
echo $mydata['content'];
} else {
echo mysql_error();
}
?>
CS346
16
<?php
//dbconnector.php
//Define the mysql connection variables.
define ("MYSQLHOST", "localhost");
define ("MYSQLUSER", "huen");
define ("MYSQLPASS", "student_id");
define ("MYSQLDB", "huen");
CS346
// DB username= email username
// id without leading 0
// assigned DB=email username
17
//dbconnector.php continued
function opendatabase() {
$db = mysql_connect (MYSQLHOST, MYSQLUSER, MYSQLPASS);
try {
if (!$db){
$exceptionstring = "Error connection to database: <br />";
$exceptionstring .= mysql_errno() . ": " . mysql_error();
throw new exception ($exceptionstring);
} else {
mysql_select_db (MYSQLDB,$db);
}
return $db;
} catch (exception $e) {
echo $e->getmessage();
die();
}
}
?>
5/22/2017CS346 Fall 2007
CS346
18
Notable about dbconnector.php

Proprietary DB login information located in
only one place




Security protection
Easy to administer
Provides DB connection and selection of DB
Exception handling of DB connection

Displays error number and error message
CS346
19
Important Design precautions in DB access

Avoid overloading the DB



Each click generates an AJAX request to the DB
Consider consequences of 3 accesses/per user for a busy
site
Ergonomics of loading DB result



If you have a DB error message, it may spill over the
enclosure
AJAX tends to load content into small compact space
Solution? Email error message to administrator but only a
small message to the user
CS346
20
Important Design precautions in DB access

Security



Perhaps Ajax more vulnerable than full-on-page
rendered scripts
Javascript is visible and may be sniffed out
GET requests may introduce code injection – SQL
injection
CS346
21
SQL Injection

SQL Injection


Passing malicious code into the query string to
cause problems with any dynamic queries
Precaution about the query string!!



mysql_real_escape_string
Wrap variables from query string with addslashes
function for string variables
intval function (for integer bases variables)
CS346
22
SQL Injection Example 1
http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php
A sample string gathered from a normal user and a bad user trying to use
SQL Injection. We asked the users for their login, which will be used to run
a SELECT statement to get their information.
MySQL & PHP Code:
// a good user's name
$name = "timmy";
$query = "SELECT * FROM customers WHERE username = '$name'";
echo "Normal: " . $query . "<br />";
// user input that uses SQL Injection
$name_bad = "' OR 1'"; // Note the double quotes and single quotes
// our MySQL query builder, however, not a very safe one
$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
// display what the new query will look like, with injection
echo "Injection: " . $query_bad;
CS346
23
What actually gets built in SQL query?
Normal: SELECT * FROM customers WHERE username = 'timmy'
Injection: SELECT * FROM customers WHERE username = '' OR 1''
Normal query is fine - select everything from customers that has a username
equal to timmy as intended.
BUT the injection attack made the query behave differently than intended.
• By using a single quote (') the string part of our MySQL query is ended
• username = ' '
• an OR clause of 1 (always true) is added on to our WHERE statement with
username = ' ' OR 1
This OR clause of 1 will always be true and so every single entry in the
"customers" table would be selected by this statement!
CS346
24
More Serious SQL Injection Attacks
http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php
MySQL & PHP Code:
$name_evil = "'; DELETE FROM customers WHERE 1 or username = '";
// our MySQL query builder really should check for injection
$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
// the new evil injection query would include a DELETE statement
echo "Injection: " . $query_evil;
Resulting Query:
SELECT * FROM customers WHERE username = ' '; DELETE FROM
customers WHERE 1 or username = ' '
This query with the injected DELETE statement, when run, would completely
empty your "customers" table.
CS346
25
How do we avoid this SQL injection?

Injection Prevention mysql_real_escape_string()

use function mysql_real_escape_string.


takes the string as argument in a MySQL query
returns the same string with all SQL Injection
attempts safely escaped.

Replaces quotes(') a user might enter with a MySQLsafe substitute, an escaped quote \'.
CS346
26
Retry the previous SQL Attack 1
MySQL & PHP Code:
$name_bad = "' OR 1'";
$name_bad = mysql_real_escape_string($name_bad);
$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
echo "Escaped Bad Injection: <br />" . $query_bad . "<br />";
Resulting Query
Escaped Bad Injection:
SELECT * FROM customers WHERE username = '\' OR 1\''
The DB will just search for a ridiculous username \' OR 1\'
Harm avoided.
CS346
27
Retry the previous SQL Attack 2
MySQL & PHP Code:
$name_evil = "'; DELETE FROM customers WHERE 1 or username = '";
$name_evil = mysql_real_escape_string($name_evil);
$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
echo "Escaped Evil Injection: <br />" . $query_evil;
Resulting query
Escaped Evil Injection:
SELECT * FROM customers WHERE username = '\'; DELETE FROM
customers WHERE 1 or username = \''
Username is the whole string
\'; DELETE FROM customers WHERE 1 or username = \'
CS346
28
Calendar example with Ajax
and database
Continue with the Calendar example
CS346
29
1. Create a DB table
mysql> CREATE TABLE task (
-> taskid INT AUTO_INCREMENT PRIMARY KEY,
-> userid INT,
-> thedate DATE,
-> description TEXT
-> );
Query OK, 0 rows affected (0.06 sec)
CS346
30
Check
mysql> describe task;
+-------------+---------+------+-----+---------+----------------+
| Field
| Type
| Null | Key | Default | Extra
|
+-------------+---------+------+-----+---------+----------------+
| taskid
| int(11) | NO
| PRI | NULL
| auto_increment |
| userid
| int(11) | YES |
| NULL
|
|
| thedate
| date
| YES |
| NULL
|
|
| description | text
| YES |
| NULL
|
|
+-------------+---------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
CS346
31
Use PHP scripts to create, insert and
display DB table in CSlabserv1
Re-use the earlier PHP scripts for creating
tables, inserting, displaying contents, drop DB
and drop tables, now in a directory db
CS346
32
Creating a database table task with
scripts in cslabserve1/huen/db
CS346
33
Note: don’t enter a field length for date and int. It will lead to an error for date and restrictive for int.
CS346
34
List tables in database huen
CS346
35
Insert records into table task
Response
CS346
36
CS346
37
CS346
38
CS346
39
CS346
40
Query the tasks in Calendar
CS346
41
Create another table user
CS346
42
CS346
43
Adding entries to DB table user
CS346
44
Add another user John Doe to user
CS346
45
Displaying contents of DB table user
CS346
46
2. Use dbconnector.php




The PHP scripts keep repeating the DB
connection script
Put the connection in one file
dbconnector.php
Include this in any application where you
need to access database
Your code just refers to $db
CS346
47
<?php
//dbconnector.php
//Define the mysql connection variables.
define ("MYSQLHOST", "localhost");
define ("MYSQLUSER", "huen");
// DB username= email username
define ("MYSQLPASS", "student_id");
// id without leading 0
define ("MYSQLDB", "huen");
// assigned DB=email username
function opendatabase() {
$db = mysql_connect (MYSQLHOST,MYSQLUSER,MYSQLPASS);
try {
if (!$db){
$exceptionstring = "Error connection to database: <br />";
$exceptionstring .= mysql_errno() . ": " . mysql_error();
throw new exception ($exceptionstring);
} else {
mysql_select_db (MYSQLDB,$db);
}
return $db;
} catch (exception $e) {
echo $e->getmessage();
die();
}
}
CS346
?>
48
48
3. Modify autocomplete.php




Instead of static array in autocomplete.php, use DB access
LIKE and NOT LIKE have two search helper symobls.
 underscore _ character that looks for one character
 percentage % character that looks for zero or more
characters.
$sql = mysql_query("SELECT * FROM table_name WHERE
columnname LIKE value%");
while ($row = mysql_fetch_row($sql)) {
echo "$row[0] $row[1] $row[2] <br />";
}
The query will only pick out the rows that provide a TRUE result
according to the WHERE equation. The equation will equal the
LIKE VALUE plus some possible extra characters afterwards.
CS346
49
Example of LIKE
$sql = mysql_query("SELECT * FROM address_book
WHERE last_name LIKE 'Stan%'");
while ($row = mysql_fetch_row($sql)) {
echo "$row[0] $row[1] $row[2] <br />";
}
Search the address_book table and compare all of the
data in the last_name column for any values starting with
'Stan' and ending with zero or more characters afterwards.
The LIKE search is not case sensitive, so it will accept
anything starting with 'stan' as well.
The WHILE loop then prints out the results found if both
equations are found TRUE.
CS346
50
3. Modify autocomplete.php
Protect yourself with mysql_real_escape_string
<?php
//autocomp.php
//Add in our database connector.
require_once ("dbconnector.php");
//And open a database connection.
$db = opendatabase();
$foundarr = array ();
//Setup the dynamic query string.
$querystr = "SELECT name FROM user WHERE name LIKE
LOWER('%" . mysql_real_escape_string ($_GET['sstring']) . "%')
ORDER BY name ASC";
CS346
51
autocomplete.php modification cont’d
if ($userquery = mysql_query ($querystr)){
while ($userdata = mysql_fetch_array ($userquery)){
if (!get_magic_quotes_gpc()){
$foundarr[] = stripslashes ($userdata['name']);
} else {
$foundarr[] = $userdata['name'];
}
}
} else {
echo mysql_error();
}
See get_magic_quotes_gpc() in PHP manual and example
CS346
52
mysql_real_escape_string
mysql_real_escape_string — Escapes special characters in a string for use in
a SQL statement
Syntax:
string mysql_real_escape_string ( string $unescaped_string [, resource
$link_identifier ] )
Description:
Escapes special characters in the unescaped_string , taking into account the
current character set of the connection so that it is safe to place it in a
mysql_query(). If binary data is to be inserted, this function must be used.
mysql_real_escape_string() calls MySQL's library function
mysql_real_escape_string, which prepends backslashes to the following
characters: \x00, \n, \r, \, ', " and \x1a.
This function must always (with few exceptions) be used to make data safe
before sending a query to MySQL.
CS346
53
Another PHP function: addslashes()
string addslashes ( string $str )
Returns a string with backslashes before characters that
need to be quoted in database queries etc. These
characters are single quote ('), double quote ("), backslash
(\) and NUL (the NULL byte).
mysql_real_escape_string is specific to MySQL.
Addslashes is just a general function which may apply to
other things as well as MySQL.
5/22/2017
CS346
54
get_magic_quotes_gpc – security
feature
get_magic_quotes_gpc
(PHP 4, PHP 5)
get_magic_quotes_gpc — Gets the current configuration
setting of magic quotes gpc
Description
int get_magic_quotes_gpc ( void )
Returns the current configuration setting of
magic_quotes_gpc
Keep in mind that the setting magic_quotes_gpc will not work
at runtime.
For more information about magic_quotes, see this security
section.
Return Values
Returns 0 if magic quotes gpc are off, 1 otherwise.
CS346
55
get_magic_quotes_gpc() example
<?php
echo get_magic_quotes_gpc();
// 1 => magic quotes are on
echo $_POST['lastname'];
// O\'reilly
echo addslashes($_POST['lastname']); // O\\\'reilly
if (!get_magic_quotes_gpc()) {
$lastname = addslashes($_POST['lastname']);
} else {
$lastname = $_POST['lastname'];
}
echo $lastname; // O\'reilly
$sql = "INSERT INTO lastnames (lastname) VALUES ('$lastname')";
?>
CS346
56
autocomplete.php modification cont’d
//If we have any matches, then we can go through and display them.
if (count ($foundarr) > 0){
?>
<div style="background: #CCCCCC; border-style: solid; border-width: 1px; border-color:
#000000;">
<?php
?>
<?php
<?php
}
?>
</div>
<?php
for ($i = 0; $i < count ($foundarr); $i++){
<div style="padding: 4px; height: 14px;"
onmouseover="this.style.background = '#EEEEEE'"
onmouseout="this.style.background = '#CCCCCC'"
onclick="setvalue ('<?php echo $foundarr[$i]; ?>')">
echo $foundarr[$i]; ?></div>
}
?>
CS346
57
4. Modifying the validator.php
<?php
//validator.php
//Add in our database connector.
require_once ("dbconnector.php");
//And open a database connection.
$db = opendatabase();
//Setup the dynamic query string.
$querystr = "SELECT userid FROM user WHERE
name = LOWER('" . mysql_real_escape_string
($_GET['sstring']) . "')";
CS346
58
4. Modifying the validator.php cont’d
if ($userquery = mysql_query ($querystr)){
if (mysql_num_rows ($userquery) == 0){
//Then return with an error.
?><span style="color: #FF0000;">Name not found.</span>
<?php
} else {
//At this point we would go to the processing script.
?><span style="color: #FF0000;">Form would now submit.</span>
<?php
}
} else {
echo mysql_error();
}
?>
CS346
59
Autocomplete thru database with Ajax
CS346
60
Validation through database with Ajax
CS346
61
5. Modifying taskchecker.php for calendar
lookup of taks
<?php
//taskchecker.php
//Add in the database connector.
require_once ("dbconnector.php");
//Open the database.
$db = opendatabase();
//Setup the dynamic query string.
$querystr = "SELECT description FROM task WHERE
thedate='" . addslashes ($_GET['thedate']) . "'";
CS346
62
if ($datequery = mysql_query ($querystr)){
if (mysql_num_rows ($datequery) > 0){
?>
<div style="width: 150px; background: #FFBC37; border-style: solid;
border-color: #000000; border-width: 1px;">
<div style="padding: 10px;">
<?php
while ($datedata = mysql_fetch_array ($datequery)){
if (!get_magic_quotes_gpc()){
echo stripslashes ($datedata['description']);
} else {
echo $datedata['description'];
}
}
?></div></div>
<?php
}
} else { echo mysql_error();
}
//Close the database connection.
mysql_close ($db);
?>
CS346
63
63
Tool tip with database and Ajax
CS346
64