Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PHP
Oscar Capuay Uceda
Contenido
DEDICATORIA
AGRADECIMIENTOS
INTRODUCCIN
I.
11
11
11
II. DHTML
16
HTML
FORMATO DE TEXTO CON HTML
LISTAS
COMENTARIOS NO VISIBLES EN LA PANTALLA
CARACTERES ESPECIALES
ENLACES O HIPERVNCULOS
IMGENES
TABLAS
FORMULARIOS
HTML 4
JAVASCRIPT
ELEMENTOS BSICOS
COMENTARIOS
LITERALES
TIPOS DE DATOS
VARIABLES
OPERADORES
ESTRUCTURAS DE CONTROL
OBJETOS
OBJETOS PREDEFINIDOS
EVENTOS
DEFINICIN MEDIANTE CDIGO
MODELO DE OBJETOS DEL DOCUMENTO
OBJETO WINDOW
OBJETO DOCUMENT
OBJETO FORM
OTROS OBJETOS
FICHEROS .JS
HOJAS DE ESTILO EN CASCADA
SINTAXIS Y TIPOS BSICOS DE DATOS EN CSS2
PALABRAS CLAVE
16
19
19
22
23
25
28
31
38
45
61
62
62
63
64
64
65
68
70
71
75
77
78
79
82
83
88
90
91
95
97
99
QUE ES PHP?
VARIABLES
CONSTANTES
TIPOS DE DATOS
EXPRESIONES
OPERADORES
OPERADORES DE ARITMTICA
OPERADORES DE ASIGNACIN
OPERADORES DE COMPARACIN
OPERADORES DE CONTROL DE ERRORES
OPERADORES DE EJECUCIN
OPERADORES DE INCREMENTO/DECREMENTO
OPERADORES DE LGICA
OPERADORES DE CADENA
OPERADORES DE MATRICES
OPERADORES DE TIPO
99
99
99
100
100
102
103
103
104
105
106
106
108
108
109
110
113
SI (CONDICIONAL): IF
ELSE
ELSEIF
FOR
WHILE
DO..WHILE
113
114
114
115
115
115
117
124
129
132
132
137
143
151
158
165
170
177
187
CLASES EN PHP
INSTANCIA DE UN OBJETO
EXTENDIENDO OBJETOS
187
187
188
189
191
191
193
194
202
205
205
212
215
215
218
221
225
225
227
229
242
246
248
253
257
IMGENES
ARCHIVOS PDF
FPDF
ARCHIVOS XLS
257
264
264
274
281
AJAX
XAJAX
EVENTOS CON XAJAX
TRABAJO CON FORMULARIOS EN XAJAX
ERROR COMN
BSQUEDA EN BASE DE DATOS CON XAJAX
ADMINISTRACIN DE DATOS CON AJAX
CONTROLADOR CON AJAX
CAPA DE DATOS CON AJAX
VISTA CON AJAX
281
282
291
293
298
299
301
301
306
308
X. REFERENCIAS BIBLIOGRAFICAS
313
XI. ANEXOS
314
LISTA DE EJEMPLOS
LISTA DE TABLAS
LISTA DE FIGURAS
314
318
319
V.
Pagina01.php
<HTML>
<HEAD>
<TITLE> Primer Ejemplo PHP </TITLE>
</HEAD>
<BODY>
El siguiente código imprime Hipertext Preprocessor<BR>
<?php
echo "Hipertext Preprocessor";
?>
</BODY>
</HTML>
Cuando un cliente Web (navegador o browser) hace una solicitud a un
servidor Web, ste ubica el archivo solicitado y verifica si contiene cdigo
PHP o no, en caso que slo sea HTML, el archivo es enviado directamente
al cliente, pero en caso que tenga cdigo PHP es enviado a ser procesado el
documento que ha sido solicitado para ser procesado y luego enviar el
resultado del procesamiento al cliente. Segn el ejemplo anterior, el
documento sera enviado a ser procesado, en este proceso se interpretara
las lneas de cdigo y despus el resultado sera enviado al cliente.
A continuacin veremos el resultado de la solicitud y procesamiento de la
pgina programada anteriormente (pagina01.php).
Pagina01.php
<HTML>
<HEAD>
<TITLE> Primer Ejemplo PHP </TITLE>
</HEAD>
<BODY>
El siguiente código imprime Hipertext Preprocessor<BR>
Hipertext Preprocessor
Oscar E Capuay Uceda
117
118
Comentarios
<?php
// Este es un ejemplo de una lnea
/*
Este es otro ejemplo,
pero tiene
varias lneas
comentadas
*/
?>
Ejemplo 57:
Sentencia if (1)
pagina02.php
<HTML>
<HEAD>
<TITLE> Ejemplo de la sentencia if </TITLE>
</HEAD>
<BODY>
El siguiente código utiliza la sentencia if de php<BR>
<?php
$nota=12;
if($nota>=10.5)
echo
"<em>Felicitaciones<em>,
Ud.
obtuvo
el
calificativo
de
<strong>$nota</strong> (APROBADO)";
else
echo
"Ud.
obtuvo
el
calificativo
de
<strong>$nota</strong>
(DESAPROBADO)";
?>
</BODY>
</HTML>
Ejemplo 58:
Sentencia if (2)
pagina03.php
<HTML>
Oscar E Capuay Uceda
119
Sentencia if (3)
pagina04.php
<HTML>
<HEAD>
<TITLE> Ejemplo de la sentencia if </TITLE>
</HEAD>
<BODY>
El siguiente código utiliza la sentencia if de php<BR>
<?php
$nota=12;
if($nota>=10.5)
{ ?>
<em>Felicitaciones<em>, Ud. obtuvo el calificativo de <strong><?php echo
$nota ?></strong> (APROBADO)
<?php }
else
{ ?>
Ud. obtuvo el calificativo de <strong><?php echo $nota ?></strong>
(DESAPROBADO)
<?php }
?>
</BODY>
</HTML>
Todos los ejemplos de la sentencia if generan la siguiente salida Web.
120
Pagina05.php
<HTML>
<HEAD>
<TITLE> Ejemplo de la sentencia for </TITLE>
</HEAD>
<BODY>
Uso de la sentencia for de php<BR>
<?php
$filas=15;
echo "<table border=\"1\">"; //iniciamos la tabla
for($i=1;$i<=$filas;$i++) //creamos varias filas con el for
{
echo "<tr><td>$i</td><tr>"; // escribir fila con el valor de: i
}
echo "</table>"; //cerramos la tabla
?>
</BODY>
</HTML>
Resultado Web
121
pagina06.php
<HTML>
<HEAD><TITLE> Ejemplo de la sentencia for </TITLE></HEAD>
<BODY> Uso de la sentencia for de php<BR>
<?php
$filas=15; $columnas=5;
echo "<table border=\"1\">"; //iniciamos la tabla
for($i=1;$i<=$filas;$i++) //creamos varias filas con el for
{
echo "<tr>"; // crear fila
for($j=1;$j<=$columnas;$j++)
{
echo "<td>$i $j</td>"; //escribir columnas (celdas)
}
echo "<tr>"; // terminar la fila
}
echo "</table>"; //cerramos la tabla
?>
</BODY>
</HTML>
Oscar E Capuay Uceda
122
123
formulario01.html
<html>
<head>
<title>Formulario</title>
</head>
<body>
<form name="form1" method="post" action="pagina08.php">
Ingresa tu nombre
<input name="txtnombre" type="text" id="txtnombre">
<input type="submit" name="Submit" value="Enviar">
</form>
</body>
</html>
En la etiqueta form, en su propiedad action, especificamos el destino de los
datos, es decir, la pgina PHP que recibir los datos del formulario. En este
caso pagina08.php, y no olvidemos que en el mtodo estamos especificando
POST.
Adems debemos tomar en cuenta el nombre del objeto (caja de texto
input tipo text) txtnombre, pues ser en nombre que usaremos en la pgina
de destino.
pagina08.php
<HTML>
<HEAD><TITLE> Ejemplo de envio de datos</TITLE></HEAD>
<BODY>
Tu nombre es:
<?php
echo $_POST[txtnombre];
?>
</table>
</BODY>
</HTML>
En esta pgina podemos ver que usamos el array $_POST de PHP para
acceder a los datos enviados a travs de este mtodo. Tambien podemos
Oscar E Capuay Uceda
124
125
126
127
128
formulario04.html
<html>
<head>
Oscar E Capuay Uceda
129
130
131
132
Figura 72.
133
134
135
136
137
138
139
140
141
Figura 91. Operacin realizada con xito y el script SQL que ha sido
ejecutado.
Siempre phpmyadmin nos mostrar el script SQL que acabamos de ejecutar,
en este caso la orden de insercin en la tabla persona.
Luego podemos ver la lista de registros haciendo click en Examinar.
142
Conexin a MySQL
pagina12.php
<?php
$conex=mysql_connect("localhost","root","") or die(mysql_error());
mysql_select_db("dbdemo",$conex) or die(mysql_error());
?>
La funcin mysql_connect abre una conexin a un servidor MySQL, y
necesita para ello tres parmetros: el nombre o direccin del servidor de
base de datos, un nombre de usuario y su contrasea. Podemos observar
luego de la funcin mysql_connect que aparece el operador OR el cual nos
permite ejecutar la orden die() en caso que la conexin fallara. La orden die()
imprime un mensaje y termina el script actual, en este caso el mensaje ser
el resultado de la ejecucin de la funcin mysql_error() retorna el texto del
error de la ltima funcin MySQL o '' (cadena vaca) si no ocurri error.
Una vez hecha la conexin almacenamos en la variable $conex el
identificador de enlace de dicha conexin. Esta variable la utilizaremos para
seleccionar la base de datos a la cual accederemos mediante la funcin
mysql_select_db() que tiene como primer parmetro el nombre de la base de
datos.
Ahora veremos una pgina que incluye el script escrito en pagina12.php para
realizar la conexin y luego hacer una consulta de todos los registros de la
tabla persona.
Ejemplo 66:
Listado de registros
pagina13.php
<?php
include "pagina12.php"; //incluimos la conexion
$sql="select * from persona"; //consulta sql
$rspersona=mysql_query($sql) or die(mysql_error());//ejecucion de la
sentencia sql
while($reg=mysql_fetch_array($rspersona)) {
echo $reg[idpersona]." - ".$reg[nombres]." ".$reg[apellidos]."<br>";
}
?>
Podemos ver en el script que con la funcin mysql_query podemos ejecutar
una sentencia SQL la cual almacena el resultado en la variable $rspersona.
Oscar E Capuay Uceda
143
144
Ejemplo 68:
Formulario05.html
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Nuevo registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pagina15.php">
Oscar E Capuay Uceda
145
146
Edicin de registros
Pagina16.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>
<?php
include "pagina12.php";
$sql="select * from persona where idpersona='$_GET[idpersona]'";
$rs=mysql_query($sql) or die(mysql_error());
//ejecutar sentencia
if(mysql_num_rows($rs)>0)
147
148
pagina17.php
<?php
include "pagina12.php";
//sentencia para editar el registro
$sql="update persona set nombres='$_POST[nombres]',
apellidos='$_POST[apellidos]', email='$_POST[email]',
telefono='$_POST[telefono]' where idpersona='$_POST[idpersona]'";
//ejecutar sentencia
mysql_query($sql) or die(mysql_error());
echo "La persona fue actualizada exitosamente<br>";
echo "<a href='pagina14.php'>Listado de Personas</a>";
?>
Resultado Web:
Eliminacin de registros
pagina18.php
<?php
include "pagina12.php";
//sentencia para eliminar el registro
$sql="delete from persona where idpersona='$_GET[idpersona]'";
Oscar E Capuay Uceda
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
Conexin a PostgreSQL
pagina22.php
<?php
//conexion al servidor PostgreSQL
$conex=pg_connect("host=localhost dbname=dbdemo port=5432 user=oscar
password=123456") or die("Error en la conexin");
?>
pagina23.php
<?php
include "pagina22.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=pg_query($sql) or die(pg_last_error($conex));
while($reg=pg_fetch_array($rspersona)) {
echo $reg[idpersona]." - ".$reg[nombres]." ".$reg[apellidos]."<br>";
}
?>
La funcin pg_last_error() muestra el ltimo error ocurrido en la conexin
activa, la cual es el parmetro.
170
pagina24.php
<?php
include "pagina22.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=pg_query($sql) or die(pg_last_error($conex));
?>
<table>
<tr>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
<?php
//mostrar los registros
while($registro=pg_fetch_array($rspersona))
{ ?>
<tr>
<td><?php echo "$registro[idpersona]"?></td>
<td><?php echo "$registro[nombres]"?></td>
<td><?php echo "$registro[apellidos]"?></td>
<td><a href="pagina26.php?idpersona=<?php echo
"$registro[idpersona]"?>">editar</a></td>
<td><a href="pagina28.php?idpersona=<?php echo
"$registro[idpersona]"?>">eliminar</a></td>
</tr>
<?php
}
//Liberar conjunto de resultados
pg_free_result($rspersona);
Oscar E Capuay Uceda
171
formulario06.html
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Nuevo registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pagina25.php">
<table width="80%" border="0" align="center">
<tr> <th colspan="2">Nuevo Registro</th> </tr>
<tr>
<td>Nombres</td> <td><input name="nombres" type="text"
id="nombres" size="50" maxlength="50" /></td>
</tr>
<tr>
<td>Apellidos</td> <td><input name="apellidos" type="text"
id="apellidos" size="50" maxlength="50" /></td>
</tr>
<tr>
172
173
pagina26.php
<html>
<head>
<?php
include "pagina22.php";
$sql="select * from persona where idpersona='$_GET[idpersona]'";
$rs=pg_query($sql) or die(pg_last_error());
if(pg_num_rows($rs)>0) $registro=pg_fetch_array($rs);
?>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Edición de registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pagina27.php">
<input type="hidden" name="idpersona" value="<?php echo
$_GET[idpersona]?>">
<table width="80%" border="0" align="center">
<tr> <th colspan="2">Edición de Persona</th> </tr>
<tr>
<td>Nombres</td> <td><input name="nombres" type="text"
id="nombres" size="50" maxlength="50" value="<?php echo
$registro[nombres]?>" /></td>
</tr>
<tr>
<td>Apellidos</td>
<td><input name="apellidos" type="text" id="apellidos" size="50"
maxlength="50" value="<?php echo $registro[apellidos]?>" /></td>
</tr>
<tr>
<td>E-Mail</td>
<td><input name="email" type="text" id="email" size="50"
maxlength="100" value="<?php echo $registro[email]?>"/></td>
</tr>
Oscar E Capuay Uceda
174
175
pagina28.php
<?php
include "pagina22.php";
//sentencia para eliminar el registro
$sql="delete from persona where idpersona='$_GET[idpersona]'";
//ejecutar sentencia
pg_query($sql) or die(pg_last_error());
echo "La persona fue eliminada exitosamente<br>";
echo "<a href='pagina24.php'>Listado de Personas</a>";
?>
176
177
178
179
Conexin a MS-SQLServer
pagina29.php
<?php
//conexion al servidor MS-SQLServer
$conex=mssql_connect("LAPTOP\\","oscar","123456") or die("Error en la
conexin");
mssql_select_db("dbdemo",$conex) or die("Error al seleccionar la BD");
?>
Ahora probemos listando los registros.
pagina30.php
<?php
include "pagina29.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=mssql_query($sql) or die("Error sql");
while($reg=mssql_fetch_array($rspersona)) {
echo $reg[idpersona]." - ".$reg[nombres]." ".$reg[apellidos]."<br>";
}
?>
Resultado Web:
180
Listado de registros
pagina31.php
<?php
include "pagina29.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=mssql_query($sql) or die("error en la consulta");
?>
<table>
<tr>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
<?php
//mostrar los registros
while($registro=mssql_fetch_array($rspersona))
{ ?>
<tr>
<td><?php echo "$registro[idpersona]"?></td>
<td><?php echo "$registro[nombres]"?></td>
<td><?php echo "$registro[apellidos]"?></td>
<td><a href="pagina33.php?idpersona=<?php echo
"$registro[idpersona]"?>">editar</a></td>
<td><a href="pagina35.php?idpersona=<?php echo
"$registro[idpersona]"?>">eliminar</a></td>
</tr>
<?php
}
//Liberar conjunto de resultados
mssql_free_result($rspersona);
// Cerrar conexion
mssql_close($conex);
?>
181
Ejemplo 78:
formulario07.html
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Nuevo registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pagina32.php">
<table width="80%" border="0" align="center">
<tr>
<th colspan="2">Nuevo Registro</th>
</tr>
<tr>
<td>Nombres</td> <td><input name="nombres" type="text"
id="nombres" size="50" maxlength="50" /></td>
</tr>
<tr>
<td>Apellidos</td> <td><input name="apellidos" type="text"
id="apellidos" size="50" maxlength="50" /></td>
</tr>
<tr>
<td>E-Mail</td> <td><input name="email" type="text" id="email"
size="50" maxlength="100" /></td>
</tr>
<tr>
<td>Teléfono</td> <td><input name="telefono" type="text"
id="telefono" maxlength="15" /></td>
</tr>
<tr>
<th colspan="2"><input name="Submit" type="submit" class="boton"
value="Guardar" /> <input name="Submit2" type="button" class="boton"
value="Cancelar" onclick="location='pagina14.php'" /></th>
</tr>
</table>
</form>
</body>
</html>
182
183
pagina33.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>
<?php
include "pagina29.php";
$sql="select * from persona where idpersona='$_GET[idpersona]'";
$rs=mssql_query($sql) or die("error en la consulta");
//ejecutar sentencia
if(mssql_num_rows($rs)>0)
$registro=mssql_fetch_array($rs);
?>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Edición de registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pagina34.php">
<input type="hidden" name="idpersona" value="<?php echo
$_GET[idpersona]?>">
<table width="80%" border="0" align="center">
<tr>
<th colspan="2">Edición de Persona</th>
</tr>
<tr>
<td>Nombres</td>
<td><input name="nombres" type="text" id="nombres" size="50"
maxlength="50" value="<?php echo $registro[nombres]?>" /></td>
</tr>
<tr> <td>Apellidos</td>
<td><input name="apellidos" type="text" id="apellidos" size="50"
maxlength="50" value="<?php echo $registro[apellidos]?>" /></td>
</tr>
<tr> <td>E-Mail</td>
<td><input name="email" type="text" id="email" size="50" maxlength="100"
value="<?php echo $registro[email]?>"/></td>
</tr>
<tr> <td>Teléfono</td>
<td><input name="telefono" type="text" id="telefono" maxlength="15"
value="<?php echo $registro[telefono]?>"/></td>
</tr>
<tr>
<th colspan="2"><input name="Submit" type="submit" class="boton"
value="Guardar" /> <input name="Submit2" type="button" class="boton"
value="Cancelar" onclick="location='pagina31.php'" /></th>
</tr>
</table>
</form>
Oscar E Capuay Uceda
184
pagina35.php
<?php
include "pagina29.php";
//sentencia para eliminar el registro
$sql="delete from persona where idpersona='$_GET[idpersona]'";
//ejecutar sentencia
Oscar E Capuay Uceda
185
186
pagina19.php
<?php
class MiClase
{
// Declaracin de un miembro de la clase
public $variable = 'demo'; // demo es el valor por defecto de $variable
// Declaracin de un mtodo
public function ver() {
echo $this->variable; //imprime el valor de $variable
}
}
?>
Instancia de un Objeto
Para crear una instancia de un objeto, un nuevo objeto debe ser creado y
asignado a una variable. Un objeto siempre ser asignado cuando se crea
un objeto nuevo a menos que el objeto tenga un constructor definido que
arroje una excepcin en caso de error. Las clases deben ser definidas antes
de crear las instancias (y en algunos casos esto es un requerido).
Cuando se asigna una instancia de un objeto previamente creado a una
nueva variable, la nueva variable accesar a la misma instancia que la del
objeto a la que fue asignada. Este comportamiento es el mismo cuando se
pasan instancias a una funcin. Una nueva instancia de un objeto
previamente creado puede ser hecha clonndolo. [3]
Ejemplo 82:
pagina20.php
<?php
include "pagina19.php"; //definicin de MiClase
//Creando una instancia
$instancia = new MiClase();
// Asignacin del Objeto
$asignado = $instancia;
$referencia =& $instancia;
Oscar E Capuay Uceda
187
Extendiendo objetos
Una clase puede heredar mtodos y miembros de otra clase usando la
palabra 'extends' en la declaracin. No es posible extender de mltiples
clases, una clase puede heredar solo de una clase base.
Los mtodos heredados y sus miembros pueden ser evitados,
redeclarndolos con el mismo nombre con el que los defini la clase padre, a
menos que la clase padre haya definido un mtodo como final. Es posible
accesar a los mtodos o miembros redeclarados haciendo referencia a ellos
con parent::
Ejemplo 83:
pagina21.php
<?php
include "pagina19.php";
class ExtendClass extends MiClase
{
// Redefinicin de mtodo
function ver()
{
echo "clase con nuevo método\n";
parent::ver();
}
}
$extended = new ExtendClass();
$extended->ver();
?>
188
Auto carga
clase1.php
<?php
class clase1
{
// Declaracin de un miembro de la clase
public $texto = 'esta es la clase1';
// Declaracin de un mtodo
public function mostrar() {
echo $this->texto; //imprime el valor de $variable
}
}
?>
Oscar E Capuay Uceda
189
190
mysqli
Representa una conexin entres PHP y la base de datos MySQL.
Constructor
mysqli - constructor de un nuevo objeto mysqli
Mtodos
autocommit - cambia en ON u OFF las modificaciones de auto-commiting en
la base de datos.
change_user - cambia el usuario del identificador de enlace especificado.
character_set_name - regresa el conjunto de caracteres del identificador de
enlace especificado.
close - cierra una conexin previamente abierta.
commit - completa la transaccin actual.
connect - abre una nueva conexin al servidor de MySQL.
debug - realiza operaciones de rastreo.
dump_debug_info - vaca informacin de rastreo.
get_client_info - retorna la versin del cliente.
get_host_info - retorna el tipo de conexin usada.
get_server_info - retorna la versin del servidor MySQL.
get_server_version - retorna la versin del servidor MySQL
init - inicializa el objeto mysqli.
info - obtiene informacin acerca de la consulta ms recientemente
ejecutada.
kill - solicita al servidor destruir un thread de mysql.
Oscar E Capuay Uceda
191
192
mysqli_stmt
Representa una sentencia preparada.
Mtodos
bind_param - enlaza variables a una sentencia preparada.
bind_result - enlaza variables a una sentencia preparada para el
almacenamiento del resultado.
close - cierra la sentencia preparada.
data_seek - busca a una fila arbitrariamente en el resultado.
execute - ejecuta una sentencia preparada.
fetch - obtiene el resultado de la sentencia preparada en variables lmite.
free_result - libera la memoria del resultado almacenado para el manejador
de la sentencia dada.
result_metadata - obtiene un resultado de la sentencia preparada para
informacin de metadatos.
prepare - prepara una consulta SQL.
send_long_data - enva datos en partes.
reset - resetea una sentencia preparada.
Oscar E Capuay Uceda
193
Propiedades
affected_rows - retorna las filas afectadas de la ltima sentencia ejecutada.
errno - retorna el cdigo de error para la llamada a funcin ms reciente.
error - retorna el mensaje de error para la llamada a funcin ms reciente.
param_count - retorna el numero de parmetros para la sentencia preparada
dada.
sqlstate - retorna una cadena conteniendo el cdigo de error SQLSTATE
para la llamada a funcin ms reciente.
mysqli_result
Representa el resultado obtenido de la consulta hecha en la base de datos.
Mtodos
close - cierra el resultado.
data_seek - mueve el puntero interno del resultado.
fetch_field - obtiene la informacin de la columna en el resultado.
fetch_fields - obtiene la informacin para todas las columnas del resultado.
fetch_field_direct - obtiene informacin de la columna para la columna dada.
fetch_array - recupera una fila como una matriz asociativa, una matriz
numrica, o ambos.
fetch_assoc - obtiene una fuka como una matriz asociativa.
fetch_object - obtiene una fila como un objeto.
fetch_row - obtiene una fila como una matriz enumerada.
close - libera la memoria ocupada por el resultado.
field_seek - fija el apuntador del resultado a la posicin especificada.
Propiedades
current_field - retorna la posicin de puntero actual.
field_count - retorna el nmero de campos en el resultado.
194
Ejemplo 85:
mysqli-connect.php
<?php
$mysqli = new mysqli("localhost", "root", "", "dbdemo");
/* verifica la conexin */
if (mysqli_connect_errno()) {
printf("Conexin fallida:<br> %s\n", mysqli_connect_error());
exit();
}
printf("Server MySQL:<br> %s\n", $mysqli->host_info);
/* Cerrar la conexin */
$mysqli->close();
?>
Resultado Web:
195
Ejemplo 86:
mysqli-lista.php
<?php
include "mysqli-conexion.php"; //incluimos la conexin
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=$mysqli->query($sql) or die($mysqli->error);
//listado
while($reg=$rspersona->fetch_object()) {
echo $reg->idpersona." - ".$reg->nombres." ".$reg->apellidos."<br>";
}
?>
Resultado Web:
196
formulario08.html
<!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">
Oscar E Capuay Uceda
197
198
mysqli-insertar.php
<?php
include "mysqli-conexion.php";
//sentencia para insertar el usuario
$sql="insert into persona
values('','$_POST[nombres]','$_POST[apellidos]','$_POST[email]','$_POST[t
elefono]')";
//ejecutar sentencia
$mysqli->query($sql) or die($mysqli->error);
echo "La persona fue registrada exitosamente<br>";
echo "<a href='mysqli-listado.php'>Listado de Personas</a>";
?>
Resultado Web:
mysqli-editar.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>
<?php
include "mysqli-conexion.php";
$sql="select * from persona where idpersona='$_GET[idpersona]'";
$rs=$mysqli->query($sql) or die($mysqli->error);
//ejecutar sentencia
if($rs->num_rows>0)
$registro=$rs->fetch_object();
?>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Edición de registro</title>
</head>
199
200
mysql-eliminar.php
<?php
include "mysqli-conexion.php";
//sentencia para eliminar el registro
$sql="delete from persona where idpersona='$_GET[idpersona]'";
//ejecutar sentencia
$mysqli->query($sql) or die($mysqli->error());
echo "La persona fue eliminada exitosamente<br>";
echo "<a href='mysqli-listado.php'>Listado de Personas</a>";
?>
Resultado Web:
201
Paginando resultados
Ejemplo 90:
Paginacin de resultados
mysqli-listado-paginacion.php
<?php
include "mysqli-conexion.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=$mysqli->query($sql) or die($mysqli->error);
$numreg=$rspersona->num_rows;
$regxpag=3;
if(!isset($_GET['p']))$_GET['p']=1;
$inicio=$regxpag*($_GET['p']-1);
$sql=$sql ." limit $inicio,$regxpag";
$numpag=ceil($numreg/$regxpag);
$rspersona=$mysqli->query($sql) or die($mysqli->error);
echo "Registros encontrados:" . $numreg;
?>
<table>
<tr>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
<?php
//mostrar los registros
while($registro=$rspersona->fetch_object())
{ ?>
<tr>
<td><?php echo "$registro->idpersona"?></td>
<td><?php echo "$registro->nombres"?></td>
<td><?php echo "$registro->apellidos"?></td>
<td><a href="mysqli-editar.php?idpersona=<?php echo "$registro>idpersona"?>">editar</a></td>
<td><a href="mysqli-eliminar.php?idpersona=<?php echo "$registro>idpersona"?>">eliminar</a></td>
</tr>
<?php
}
$rspersona->close(); //cerramos resultado de la consulta
$mysqli->close(); //cerr=amos la conexin
?>
</table>
Oscar E Capuay Uceda
202
203
204
Arquitectura MVC
Todos los que estamos inmersos en el mundo de la programacin sabemos
que en todo programa los datos que se procesan pueden ser ingresados y
mostrados en formas diferentes dependiendo del tipo y diseo de la interfaz,
y sobre todo en el desarrollo Web esto se ve aun ms acentuado debido a
que los desarrolladores Web muchas veces son muy buenos programando
pero no diseando interfaces, por lo general las empresas de este rubro
optan por utilizar dos equipos de trabajo: los codificadores quienes se
encargan de implementar los algoritmos y los diseadores para darle un
buena presentacin a la aplicacin, pero las dificultades inician cuando
alguna parte del cdigo que un equipo hace influye sobre el diseo que
realiza el otro equipo. Para dar solucin a este tipo de problemas han
surgido arquitecturas de desarrollo que nos permiten desarrollar aplicaciones
separando la lgica del diseo de la interfaz, una de ellas es la Arquitectura
MVC (Modelo Vista Controlador).
205
206
207
208
_modelo.php
<?php
class ClaseX
{
protected $plantilla_propia = "_listar.php";
protected $arrayx= array();
public function show()
{
include ($this->plantilla_propia);
}//fun
public function CargarDatos()
{
$this->arrayx = array("Abel", "Marco","Pedro");
}//fun
}//class
?>
Ejemplo 92:
_listar.php
<?php
foreach ($this->arrayx as $elemento)
{
echo $elemento["nombre"];
echo "";
}//foreach
?>
Oscar E Capuay Uceda
209
_controlador.php
<?php
include ("./_modelo.php");
$objX = new ClaseX();
//aqu habra que implementar una clase que
//determine las caracteristicas de la pagina
//pero para poner un ejemplo sencillo vamos
//a saltarnos esa parte en este artculo
$titulo = "pagina nueva";
$objX->CargarDatos();
include ("_vista.php");
?>
Ejemplo 94:
_vista.php
<html>
<head>
<title><?php echo $titulo; ?></title>
</head>
<body>
<?php $objX->show(); ?>
</body>
</html>
El punto clave en una Vista como la de este ejemplo es que no uses
instrucciones PHP ms all de las que muestren datos. Por qu? Pues si la
lgica de tu aplicacin se est decidiendo en la Vista entonces para qu
queremos el Controlador? ;) Simplificando mucho el concepto eso quiere
decir que uses echo y metodos de tus objetos (Modelo) que hagan echo de
alguna forma aunque tu los llames show o muestra_datos o lo que t
quieras.
El inventor y gur del PHP Rasmus Lerdorf, public hace algn tiempo, en
febrero del ao 2006 un bastante mal entendido artculo, titulado The no
framework PHP MVC framework
Aqu, Rasmus nos habla sobre como implementar un sencillo MVC usando
solo PHP puro. Bueno, estoy de acuerdo hasta un cierto punto con este
artculo y es que implementar el MVC sin usar un framework que vaya ms
all de nuestras necesidades nos va a beneficiar en cuanto a la memoria que
usa cada script PHP. Ms tarde hablaremos sobre la optimizacin. Algunos
Oscar E Capuay Uceda
210
211
modelo_bd.php
<?php
class BaseDatos
{
protected $servidor="localhost";
protected $usuario="root";
protected $password="";
protected $link;
public $rs;
public function conectar()
{
$this->link=mysql_connect($this->servidor,$this>usuario,$this->password) or die(mysql_error());
mysql_select_db("dbdemo",$this->link) or die(mysql_error());
}
public function consultar($sql)
{
$this->rs=mysql_query($sql) or die(mysql_error());
}
} //fin clase
class ClaseDatos
{
protected $plantilla_listado = "lista_bd.php";
protected $data= array();
protected $recset;
protected $registro;
*
212
lista_bd.php
<table border="1">
<?php
while($this->leer_registro()) { ?>
<tr>
<?php
foreach($this->registro as $k => $v){
?>
<td><?php echo $this->registro[$k]?></td>
<?php
}
?>
</tr>
<?php } ?>
</table>
Ejemplo 97:
vista_bd.php
<html>
<head>
<title><?php echo $titulo; ?></title>
</head>
<body>
<?php $objData->show(); ?>
</body>
</html>
Ejemplo 98:
controlador_bd.php
<?php
include ("modelo_bd.php");
$objData = new ClaseDatos();
$sql="select * from persona";
Oscar E Capuay Uceda
213
214
Controladores PDO
Controlador
Base de Datos
PDO_DBLIB
PDO_FIREBIRD
Firebird/Interbase 6
PDO_IBM
IBM DB2
PDO_INFORMIX
PDO_MYSQL
MySQL 3.x/4.x/5.x
PDO_OCI
PDO_ODBC
PDO_PGSQL
PostgreSQL
PDO_SQLITE
Clases predefinidas
PDO
Representa una conexin entre PHP y un servidor de base de datos.
Constructor
PDO - construye un nuevo objeto PDO
Mtodos
beginTransaction inicia una transaccin.
commit - efecta la transaccin.
215
PDOStatement
Representa una sentencia preparada, luego que la sentencia es ejecutada,
un conjunto de registros.
Mtodos
bindColumn - relaciona variable a una columna de salida en un conjunto de
registros.
bindParam - relaciona una variable PHP a un parmetro en la sentencia
preparada.
bindValue - binds un valor a un parmetro en la sentencia preparada.
closeCursor - cierra el cursor, permitiendo ejecutar nuevamente la sentencia.
columnCount - retorna el nmero de columnas del conjunto de registros.
errorCode - retorna un cdigo de error, si lo hay, de la sentencia.
errorInfo - retorna un arreglo de informacin de un error, si lo hay, de la
sentencia.
execute ejecuta la sentencia preparada.
fetch lee un registro de un conjunto de registros.
216
217
pdo-connect.php
<?php
$conn = new PDO('mysql:host=localhost;dbname=dbdemo',"root","");
//$conn = new PDO('mssql:host=localhost;dbname=dbmicro',"sa","");
//$conn = new PDO('pgsql:host=localhost;dbname=dbpos',"postgres","psql");
?>
Ahora veremos una lista simple obtenida de la tabla persona.
Ejemplo 100:
pdo-lista.php
<?php
try {
include "pdo-connect.php";
foreach ($conn->query('SELECT * from persona') as $registro) {
print_r($registro);
}
$conn = null; //cierre de conexin
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>
218
pdo-listado.php
<?php
include "pdo-connect.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
$rspersona=$conn->query($sql);
?>
<form name="form1" action="pdo-eliminar.php" method="post">
<table>
<tr>
<th>Eliminar</th>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
</tr>
<?php
//mostrar los registros
while($registro=$rspersona->fetch())
{ ?>
<tr>
<td><input
type="checkbox"
name="chkelim[]"
value="<?php
$registro[idpersona]?>" /></td>
<td><?php echo $registro[idpersona]?></td>
<td><?php echo $registro[nombres]?></td>
<td><?php echo $registro[apellidos]?></td>
<td><a
href="pdo-editar.php?idpersona=<?php
$registro[idpersona]?>">editar</a></td>
</tr>
<?php
Oscar E Capuay Uceda
echo
echo
219
pdo-nuevo.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>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Nuevo registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pdo-insertar.php">
<table width="80%" border="0" align="center">
<tr>
<th colspan="2">Nuevo Registro</th>
</tr>
<tr>
<td>Nombres</td>
<td><input name="nombres" type="text" id="nombres" size="50"
maxlength="50" /></td>
Oscar E Capuay Uceda
220
Resultado Web:
221
pdo-eliminar.php
<?php
include "pdo-connect.php";
$sentencia=$conn->prepare("delete from persona where idpersona=:id");
$sentencia->bindParam(':id',$valor);
foreach($_POST[chkelim] as $indice => $valor) {
$sentencia->execute();
}
header("location: pdo-listado.php");
?>
Ejemplo 104:
pdo-editar.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>
<?php
include "pdo-connect.php";
$sql="select * from persona where idpersona=" . $_GET[idpersona];
$rspersona=$conn->query($sql);
$registro=$rspersona->fetch();
?>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Edición de registro</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="pdo-actualizar.php">
Oscar E Capuay Uceda
222
223
224
Seguridad Web
http://www.php.net/manual/es/security.general.php
225
Seguridad Web
$archivo = $_POST['archivo'];
//generamos la ruta para el borrado del archivo directorio del usuario
$directorio = "/home/$usuario";
//orden de eliminacin del archivo
unlink("$directorio/$archivo");
echo "El archivo: $archivo ha sido eliminado!";
?>
Si alguien desea atacar el sistema de archivos podra escribir en el
formulario datos para eliminar por ejemplo el archivo de passwords del
sistema operativo, en el caso que PHP tuviera acceso de root.
Ejemplo 106:
<?php
// Para el caso del nombre del usuario enviamos: "../etc"
// Para el caso del nombre del archivo enviamos: "passwd"
$usuario = $_POST['nombre_usuario'];
$archivo = $_POST['archivo'];
//generando la ruta del directorio obtendramos lo siguiente: "/home/../etc"
$directorio = "/home/$nombre_usuario";
// El archivo que se va a eliminar es: "/home/../etc/passwd"
unlink("$directiorio/$archivo");
echo "El archivo ha sido eliminado!";
?>
Para mejorar el control y la validacin de los datos enviados por el usuario
utilizaremos funciones que nos permitan verificar el tipo de datos correcto.
Por ejemplo:
if
(!ctype_alnum($nombre_usuario)
||
!preg_match('/^(?:[a-z0-9_]|\.(?!\.))+$/iD', $archivo_usuario)) {
die("Nombre de usuario o archivo incorrecto");
}
ctype_alnum: es una funcin que devuelve TRUE cuando la cadena contiene
solamente caracteres alfanumricos, es decir, letras y/o nmeros.
preg_match: es una funcin que realiza una comparacin en base a una
expresin regular.
226
Seguridad Web
Md5
md5.php
<?php
$texto="miclavedeacceso";
$cifrado=md5($texto);
echo "mi clave cifrada es:".$cifrado;
// el texto cifrado con MD5 de 128bits genera una cadena de 32 caracteres
de longitud.
?>
Resultado Web:
227
Seguridad Web
Desarrollaremos ahora un formulario para el acceso de usuarios teniendo
como supuesto que la tabla de usuarios se llama: user, y los campos donde
estn registrados
los nombres de usuario y clave de acceso son:
user_nombre y user_clave respectivamente.
El script para este caso sera:
Ejemplo 108:
acceso-md5.php
<?php
include "conexion.php"; //conexion a la BD
//datos provenientes del formulario
$usuario=$_POST[txtusuario];
$clave=$_POST[txtclave];
$clave_cifrada=md5($clave);
$sql="select * from user
user_clave='".$clave_cifrada."'";
where
user_nombre='".$usuario."'
and
$rs=mysql_query($sql) or die(mysql_error());
//si existe un usuario con dichos datos
if(mysql_num_rows($rs)==1) echo "Datos correctos";
else echo "Datos incorrectos";
?>
Con este script no sera suficiente para dar la seguridad adecuada a nuestra
aplicacin Web. A continuacin veremos otro punto importante que debemos
tomar en cuenta.
228
Seguridad Web
Inyeccin SQL
Una consulta SQL no es una orden confiable a la que no se le debe prestar
la atencin debida, sino por el contrario es en la que ms cuidado debemos
tener puesto que a travs de ella se puede burlar los controles de acceso a
cualquier sistema Web e incluso permitir el acceso a comandos del sistema
operativo.
La Inyeccin de comandos SQL es una tcnica utilizada para alterar
comandos SQL definidos en una aplicacin con la finalidad de mostrar datos,
sobrescribirlos, eliminarlos o ejecutar rdenes que no fueron establecidas
por el desarrollador. La manera de realizar las alteraciones es a travs de los
datos enviados por un usuario y su combinacin con parmetros utilizados
en las sentencias SQL. A continuacin veremos ejemplos que nos ayudarn
a ver estos casos con mayor detalle.
Ejemplo 109:
<?php
$sql="SELECT
zona=$zona";
nombre,
apellidos,
direccion
FROM
cliente
WHERE
$result = mysql_query($sql);
?>
En este ejemplo la variable $zona es enviada por el usuario. Utilizando la
variable $zona enviaremos la siguiente cadena: union select * from usuario
-En la cadena podemos ver una comilla simple ( ) al inicio y doble guin ( -- )
al final.
Si reemplazamos esta cadena en lugar de la variable $zona veremos que el
resultado de la consulta mostrar todos los datos registrados en la tabla
usuario.
Utilizando como base el ejemplo anterior haremos inyeccin SQL en una
pgina con un listado que utiliza hipervnculos para la paginacin de
resultados.
Ejemplo 110:
inyeccion01.php
<?php
include "mysqli-conexion.php"; //incluimos la conexion
$cantidad=2; //numero de registros por pagina
//verificamos si existe la variable
Oscar E Capuay Uceda
229
Seguridad Web
if(!isset($_GET[p])) $_GET[p]=0;
//hallamos el total de registros
$sql="select * from persona";
$rspersona=$mysqli->query($sql) or die($mysqli->error);
$nr=$rspersona->num_rows;
//paginacin de resultados
$sql="select idpersona,nombres,apellidos from persona limit " . $_GET[p] .
",$cantidad";
$rspersona=$mysqli->query($sql) or die($mysqli->error);
?>
<table>
<tr>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
<?php
//mostrar los registros
while($registro=$rspersona->fetch_object())
{ ?>
<tr>
<td><?php echo "$registro->idpersona"?></td>
<td><?php echo "$registro->nombres"?></td>
<td><?php echo "$registro->apellidos"?></td>
<td><a
href="mysqli-editar.php?idpersona=<?php
echo
"$registro>idpersona"?>">editar</a></td>
<td><a
href="mysqli-eliminar.php?idpersona=<?php
echo
"$registro>idpersona"?>">eliminar</a></td>
</tr>
<?php
}
?>
<tr><td colspan="5">Página:
<?php
for($i=1;$i<=ceil($nr/$cantidad);$i++)
{
$inicio=$cantidad*($i-1);
echo "<a href='?p=$inicio'>$i</a> ";
}
?>
</td></tr>
</table>
<br>
<a href="formulario08.html">Agregar Registro</a>
<?php
$rspersona->close(); //cerramos resultado de la consulta
$mysqli->close(); //cerramos la conexin
?>
230
Seguridad Web
Resultado Web:
231
Seguridad Web
232
Seguridad Web
pretenda inyectar SQL. Para el caso anterior debemos analizar y verificar
que el valor de la variable p sea un nmero obligatoriamente, entonces
aadimos la lnea:
if(!is_numeric($_GET[p])) $_GET[p]=0;
is_numeric es una funcin que devuelve TRUE si el valor de la variable es
numrico.
En caso que no sea numrico le asignamos CERO, segn la lnea de cdigo
anterior.
inyeccion02.php
<?php
include "mysqli-conexion.php"; //incluimos la conexion
$cantidad=2; //numero de registros por pagina
//verificamos si existe la variable
if(!isset($_GET[p])) $_GET[p]=0;
//hallamos el total de registros
$sql="select * from persona";
$rspersona=$mysqli->query($sql) or die($mysqli->error);
$nr=$rspersona->num_rows;
//verificamos si es p tiene valor numrico
if(!is_numeric($_GET[p])) $_GET[p]=0;
//paginacin de resultados
$sql="select idpersona,nombres,apellidos from persona limit " . $_GET[p] .
",$cantidad";
$rspersona=$mysqli->query($sql) or die($mysqli->error);
?>
<table>
<tr>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
<?php
//mostrar los registros
while($registro=$rspersona->fetch_object()) {
?>
<tr>
<td><?php echo "$registro->idpersona"?></td>
<td><?php echo "$registro->nombres"?></td>
Oscar E Capuay Uceda
233
Seguridad Web
<td><?php echo "$registro->apellidos"?></td>
<td><a
href="mysqli-editar.php?idpersona=<?php
>idpersona"?>">editar</a></td>
<td><a
href="mysqli-eliminar.php?idpersona=<?php
>idpersona"?>">eliminar</a></td>
</tr>
echo
echo
"$registro"$registro-
<?php
}
?>
<tr><td colspan="5">Página:
<?php
for($i=1;$i<=ceil($nr/$cantidad);$i++)
{
$inicio=$cantidad*($i-1);
echo "<a href='?p=$inicio'>$i</a> ";
}
?></td></tr>
</table>
<br>
<a href="formulario08.html">Agregar Registro</a>
<?php
$rspersona->close(); //cerramos resultado de la consulta
$mysqli->close(); //cerramos la conexin
?>
Con esta modificacin ejecutaremos la misma URL:
234
Seguridad Web
para esta tabla: login (nombre del usuario) y clave (password del usuario) y
luego registramos algunos registros.
235
Seguridad Web
Resultado Web:
236
Seguridad Web
SELECT * from usuario WHERE login='loquesea' AND password= OR =
Si logramos generar una cadena como la anterior entonces no
necesitaremos tener un nombre de usuario correcto ni su respectiva clave
puesto que la condicin (WHERE) siempre resultar verdadera y por lo tanto
nos devolver todos los registros de la tabla usuario. Pero para llegar a
generar la ltima cadena debemos partir de la que suponemos se ha escrito
en el script, en este caso la que est en nuestro archivo inyeccion03.php.
Cadena inicial:
$sql="SELECT * from usuario WHERE login='" . $_POST[usuario] . "' and
clave='" . $_POST[passw] . "'";
Ahora a $_POST[usuario] le podemos dar cualquier valor, en este caso:
loquesea y a $_POST[passw] le daremos el valor: ' OR ''=' , con estos
valores resultara:
SELECT * from usuario WHERE login='loquesea' AND password= OR =
Probemos esto en el navegador con nuestro formulario09.html
237
Seguridad Web
Pero si magic_quotes se encuentra inactivo tendremos el siguiente
resultado:
238
Seguridad Web
</tr>
</table>
</form>
</body>
</html>
Una vez cargado el formulario, ingresamos los datos de prueba.
Resultado Web:
get_magic_quotes_gpc y addslashes
comillas-magicas.php
<?php
if (!get_magic_quotes_gpc()) {
$password = addslashes($_POST['passw']);
} else {
$password = $_POST['passw'];
}
$sql="SELECT * from usuario WHERE login='" . $_POST[usuario] . "' and
clave='" . $password . "'";
//imprimir sentencia SQL
echo $sql;
?>
Veamos ahora el resultado:
239
Seguridad Web
Podemos notar que se le agrega un \ (slash) a cada comilla, sin importar la
configuracin de las comillas mgicas, el script anterior no ayudara a evitar
la inyeccin SQL.
Con este script mejoramos el control del acceso a usuarios, pero cabe
resaltar una funcin creada para evitar este tipo de inyecciones SQL en
servidores MySQL, llamada: mysqli_real_escape_string (programacin
orientada a objetos) o mysql_real_escape_string (programacin
procedimental). Veamos un ejemplo con estilo orientado a objetos:
Ejemplo 112:
mysqli_real_escape_string
formulario11.html
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Acceso al sistema</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="inyeccion04.php">
<table width="50%" border="0" align="center">
<tr> <th colspan="2">Acceso al sistema</th></tr>
<tr>
<td>Usuario</td> <td><input name="usuario" type="text" id="usuario"
maxlength="20" /></td>
</tr>
<tr>
<td>Password</td>
<td><input
name="passw"
type="password"
id="passw" maxlength="40" /></td>
</tr>
<tr>
<th
colspan="2"><input
name="Submit"
type="submit"
class="boton" value="Entrar" /> </th> </tr>
</table>
</form>
</body>
</html>
inyeccion04.php
<?php
//incluimos la conexion
include "mysqli-conexion.php";
$usuario =$mysqli->real_escape_string($_POST['usuario']);
$password=$mysqli->real_escape_string($_POST['passw']);
$sql="SELECT
*
from
usuario
WHERE
login='$usuario'
clave='$password'";
//imprimir sentencia SQL
Oscar E Capuay Uceda
and
240
Seguridad Web
echo $sql;
?>
Resultado Web:
241
Seguridad Web
Sesiones
Las sesiones en PHP son un mecanismo para preservar datos a lo largo de
varios accesos lo que permite construir aplicaciones Web ms
personalizadas.
A cada visitante que accede a su Web se le asigna un identificador nico,
llamado "session id" (identificador de sesin). ste se almacena en una
cookie por parte del usuario o se propaga en la URL.
Las Cookies sirven para almacenar datos en el navegador del usuario. Se
pueden poner cookies usando la funcin setcookie(). Las Cookies son parte
de la cabecera HTTP, por tanto la funcin setcookie() debe ser llamada
antes de que se produzca cualquier salida al navegador.
El soporte de las sesiones le permite registrar un nmero arbitrario de
variables que se conservarn en las siguientes peticiones. Cuando un
visitante acceda a su Web, PHP comprobar automticamente (si
session.auto_start est puesto a 1) o cuando usted lo especifique (de forma
explcita mediante session_start() o implcita a travs de session_register())
si se le ha enviado un "session id" especfico con su peticin, en cuyo caso
se recrean las variables que se haban guardado anteriormente.
Todas las variables registradas son almacenadas tras finalizar la peticin.
Las variables que estn indefinidas se marcan como no definidas. En los
subsiguientes accesos, no estarn definidas por el mdulo de sesiones a
menos que el usuario las defina ms tarde.
Las opciones de configuracin track_vars y register_globals influyen
notablemente en la forma en que las variables de la sesin se almacenan y
restauran. A partir de PHP 4.0.3, track_vars siempre est activado. A partir
de PHP 4.1.0, $_SESSION est disponible como variable global, al igual que
$_POST,
$_GET,
$_REQUEST
y
dems.
Al
contrario
que
$HTTP_SESSION_VARS, $_SESSION siempre es global. Por tanto, no se
debe usar global para $_SESSION.
Si track_vars est activado y register_globals est desactivado, slo los
miembros del vector asociativo global $HTTP_SESSION_VARS pueden ser
registrados como variables de la sesin. Las variables restauradas de la
sesin slo estarn disponibles en el vector $HTTP_SESSION_VARS.
Se recomienda usar $_SESSION (o $HTTP_SESSION_VARS con PHP
4.0.6 o inferior) por seguridad y para hacer el cdigo ms legible. Con
$_SESSION o $HTTP_SESSION_VARS, no es necesario usar las funciones
session_register() / session_unregister() / session_is_registered(). Los
usuarios pueden acceder a una variable de la sesin como si se tratase de
una variable normal.
Si register_globals est activado, todas las variables globales pueden ser
registradas como variables de la sesin, y las variables de la sesin sern
restauradas a sus correspondientes variables globales. Como PHP debe
Oscar E Capuay Uceda
242
Seguridad Web
saber qu variables globales estn registradas como variables de la sesin,
los usuarios deben registrar las variables con la funcin session_register(),
mientras que con $HTTP_SESSION_VARS/$_SESSION no es necesario
usar session_register().
Si est usando $HTTP_SESSION_VARS/$_SESSION y desactiva
register_globals, no use session_register(), session_is_registered() ni
session_unregister().
Se recomienda desactivar register_globals por motivos de seguridad y
rendimiento.
Ejemplo 113:
ingreso01.php
<form action="verifica01.php" method="post">
<table
width="70%"
border="0"
cellspacing="1"
align="center">
<caption>
Acceso al sistema
</caption>
cellpadding="2"
<tr>
<td>Usuario</td>
<td><input type="text" name="txtusuario" id="txtusuario" maxlength="20">
</td>
</tr>
<tr>
<td>Password</td>
<td><input
name="txtclave"
type="password"
id="txtclave"
maxlength="50"></td>
</tr>
<?php
if($_GET['error']==1) {
?>
<tr><td colspan="2">Datos Incorrectos</td></tr>
<?php } ?>
<tr>
<th
colspan="2"><input
type="submit"
name="Submit"
value="Entrar"></th>
</tr>
</table>
</form>
<?php
echo "Su dirección IP es: ".$_SERVER['REMOTE_ADDR'];
?>
<br>
<?php
echo "Navegador: ".$_SERVER['HTTP_USER_AGENT'];
?>
Oscar E Capuay Uceda
243
Seguridad Web
<br>
<?php
echo "Idioma: ".$_SERVER['HTTP_ACCEPT_LANGUAGE'];
?>
Resultado Web:
Ejemplo 114:
verifica01.php
<?php
include "mysqli-conexion.php"; //incluimos la conexion
//Proteger de caracteres especiales a la sentencia SQL
$usuario =$mysqli->real_escape_string($_POST['txtusuario']);
$clave =$mysqli->real_escape_string($_POST['txtclave']);
//ciframos la clave escrita por el usuario para compararla en la BD
$clave=md5($clave);
//sentencia sql
$sql="select * from usuario where login='$usuario' and clave='$clave'";
//ejecutamos la consulta
$rsusuario=$mysqli->query($sql) or die($mysqli->error);
if($rsusuario->num_rows==1)
{
//datos correctos
$reg=$rsusuario->fetch_object();
session_start();
$_SESSION['idusuario']=$reg->idusuario;
$_SESSION['usuario']=$reg->usuario;
244
Seguridad Web
$_SESSION['tipo']=$reg->tipo;
} else header("location: ingreso01.php?error=1");
?>
Probamos con datos incorrectos.
245
Seguridad Web
Autenticacin HTTP
auth01.php
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Sistema Web"');
header('HTTP/1.0 401 Unauthorized');
echo 'Operación cancelada';
exit;
} else {
echo "<p>Bienvenido {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>Acceso al sistema con password:
{$_SERVER['PHP_AUTH_PW']}.</p>";
}
?>
Resultado Web:
246
Seguridad Web
Si cancelamos la operacin tenemos el siguiente resultado en el navegador,
segn lo establecido en el cdigo.
247
Seguridad Web
Login
Ahora que ya tenemos el script de autenticacin de usuarios,
desarrollaremos el script para verificar el nombre de usuario y contrasea en
la base de datos. Utilizaremos una tabla usuario, con campos que contengan
el nombre y contrasea del usuario.
248
Seguridad Web
Como podemos observar en la figura anterior, para ingresar un nuevo
registro debemos aplicar la funcin md5 a la contrasea del usuario.
Ahora desarrollaremos el script de logeo de usuarios. Para ello podremos
usar como mecanismo de ingreso de datos el script de autenticacin
desarrollado en el tema anterior o usar un formulario HTML como el
siguiente:
Ejemplo 116:
entrar.php
<HTML>
<HEAD>
<TITLE>Login</TITLE>
</HEAD>
<BODY>
<form name="form1" action="logeo.php" method="post">
<table align="center" width="50%">
<tr><th colspan="2">Ingreso al sistema</th></tr>
<tr><td>Usuario</td>
<td><input type="text" name="txtusuario"></td></tr>
<tr><td>Password</td>
<td><input type="password" name="txtclave"></td></tr>
<tr><th colspan="2"><input type="submit" value="Entrar"></th></tr>
</table>
<?php
if($_GET['error']==1) echo "Datos Incorrectos";
if($_GET['error']==2) echo "Debe logearse";
?>
</form>
</BODY>
</HTML>
Resultado Web:
249
Seguridad Web
Ejemplo 117:
Logeo de usuarios
logeo.php
<?php
include "mysqli-conexion.php";
$usuario=$mysqli->real_escape_string($_POST['txtusuario']);
$clave=md5($_POST['txtclave']);
$sql="select * from usuario where login='$usuario' and clave='$clave'";
$rsusuario=$mysqli->query($sql) or die($mysqli->error);
if($rsusuario->num_rows==1) {
$registro=$rsusuario->fetch_object();
session_start();
$_SESSION['sidusuario']= $registro->idusuario;
$_SESSION['susuario']= $usuario;
header("location: mysqli-listado-logeado.php");
}
else header("location: entrar.php?error=1");
?>
En este script utilizamos el mtodo real_escape_string. Esta funcin es
usada para crear una cadena SQL sin inyeccin SQL. Los caracteres
codificados son NULL (ASCII 0), \n, \r, \, ', ", y Control-Z. Adems usamos la
funcin md5 para cifrar la clave escrita en el formulario y compararla con la
cadena cifrada guardada en la base de datos.
Si el nmero de registros es 1 (uno), significa que los datos son correctos y
pertenecen a uno y solo un usuario (no pueden haber varios usuarios con el
mismo nombre). Por lo que debemos iniciar una sesin utilizando la funcin
session_start. El apoyo que PHP proporciona para las sesiones consiste en
una forma de conservar ciertos datos a lo largo de los subsiguientes
accesos, lo cual le permite construir aplicaciones ms personalizadas e
incrementar el atractivo de su sitio Web.
Utilizaremos tambin, al array $_SESSION[] para registrar las variables de
sesin de nuestra aplicacin, en este caso especfico, para registrar el
identificador del usuario (idusuario) y su nombre de usuario (usuario).
A partir de PHP 4.1.0, $_SESSION est disponible como variable global, al
igual que $_POST, $_GET, $_REQUEST y dems. Al contrario que
$HTTP_SESSION_VARS, $_SESSION siempre es global. Por tanto, no se
debe usar global para $_SESSION.
Cuando los datos ingresados son incorrectos, retornar a la pgina inicial, de
lo contrario el script redirecciona el navegador hacia el listado de personas
(archivo: mysqli-listado.php), el cual, tiene dos nuevas lneas de cdigo con
respecto al ejemplo 76.
250
Seguridad Web
Resultado Web cuando los datos son incorrectos
mysqli-listado-logeado.php
<?php
session_start();
if(!isset($_SESSION['sidusuario'])) header("location: entrar.php?error=2");
include "mysqli-conexion.php"; //incluimos la conexion
//consulta sql
$sql="select * from persona";
//ejecucion de la sentencia sql
$rspersona=$mysqli->query($sql) or die($mysqli->error);
echo "Usuario:" . $_SESSION['susuario'];
?>
<table>
<tr>
<th>Id</th>
<th>Nombres</th>
<th>Apellidos</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
<?php
//mostrar los registros
while($registro=$rspersona->fetch_object())
{ ?>
<tr>
<td><?php echo "$registro->idpersona"?></td>
<td><?php echo "$registro->nombres"?></td>
<td><?php echo "$registro->apellidos"?></td>
Oscar E Capuay Uceda
251
Seguridad Web
<td><a
href="mysqli-editar.php?idpersona=<?php
echo
>idpersona"?>">editar</a></td>
<td><a
href="mysqli-eliminar.php?idpersona=<?php
echo
>idpersona"?>">eliminar</a></td>
</tr>
<?php
}
$rspersona->close(); //cerramos resultado de la consulta
$mysqli->close(); //cerr=amos la conexin
?>
</table>
<br>
<a href="formulario08.html">Agregar Registro</a>
"$registro"$registro-
Resultado Web:
252
Seguridad Web
CAPTCHA
Este nombre proviene del acrnimo de: Completely Automatic Public Turing
Test to Tell Computers and Humans Apart, que traducido al espaol
significa: Prueba de Turing pblica y automtica para diferenciar a mquinas
y humanos.
Se trata de una prueba desafo-respuesta utilizada en computacin para
determinar cundo el usuario es o no humano. El trmino se empez a
utilizar en el ao 2000 por Luis von Ahn, Manuel Blum y Nicholas J. Hopper
de la Carnegie Mellon University, y John Langford de IBM.
La tpica prueba consiste en que el usuario introduzca un conjunto de
caracteres que se muestran en una imagen distorsionada que aparece en
pantalla. Se supone que una mquina no es capaz de comprender e
introducir la secuencia de forma correcta por lo que solamente el humano
podra hacerlo.
Como el test es controlado por una mquina en lugar de un humano como
en la Prueba de Turing, tambin se denomina Prueba de Turing Inversa.
Los CAPTCHAs son utilizados para evitar que robots, tambin llamados
spambots, puedan utilizar ciertos servicios. Por ejemplo, para que no puedan
participar en encuestas, registrarse para usar cuentas de correo electrnico
(o su uso para envo de correo basura) o, ms recientemente, para evitar
que correo basura pueda ser enviado por un robot (el remitente debe pasar
el test antes de que se entregue al destinatario). [8]
El sistema CAPTCHA tiene las siguientes caractersticas por definicin:
Son completamente automatizados, es decir, no es necesario ningn
tipo de mantenimiento / intervencin humana para su realizacin.
Esto supone grandes beneficios en cuanto a fiabilidad y coste.
El algoritmo utilizado es pblico. De esta forma la ruptura de un
captcha pasa a ser un problema de inteligencia artificial y no la
ruptura de un algoritmo secreto.
A continuacin construiremos con PHP un CAPTCHA.
El primer paso es disear y programar el formulario en el que aparecer
nuestro CAPTCHA:
Ejemplo 119:
Formulario CAPTCHA
form-catcha.php
<?php
session_start();
if(isset($_POST["palabra"])) {
if($_POST["palabra"] == $_SESSION["oculto"])
die("Felicidades! Ha ledo correctamente la palabra.");
else
Oscar E Capuay Uceda
253
Seguridad Web
die("No has adivinado la palabra. Prueba otra vez");
} else {
?>
<form method="post" action="">
<img src="capu-captcha.php">
<input type="text" name="palabra">
<input type="submit" value="Comprobar">
</form>
<?php
}
?>
Ejemplo 120:
Generador CAPTCHA
capu-captcha.php
<?php
session_start();
// estas cabeceras evitan que se almacene la imagen en el cach
header ("Expires: Sat, 12 Jul 2008 09:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-store, no-cache, must-revalidate");
header ("Cache-Control: post-check=0, pre-check=0", false);
header ("Pragma: no-cache");
// creamos la imagen con el tamao determinado
$imagen = imagecreate(250, 100);
// elegimos los colores para el fondo y el texto
$rojo = mt_rand(150,200);
$verde = mt_rand(150,200);
$azul = mt_rand(200,250);
$rojo_fondo = mt_rand(80,120);
$verde_fondo = mt_rand(80,120);
$azul_fondo = mt_rand(80,200);
$rojo_basura = $rojo+55;
$verde_basura = $verde+55;
$azul_basura = $azul+5;
$color_texto = imagecolorallocate($imagen,$rojo,$verde,$azul);
$color_fondo =
imagecolorallocate($imagen,$rojo_fondo,$verde_fondo,$azul_fondo);
$color_basura =
imagecolorallocate($imagen,$rojo_basura,$verde_basura,$azul_basura);
//aplicamos el color de fondo
imagefill($imagen,0, 0, $color_fondo);
// construimos la palabra
$caracteres =
"ABCDEFGHJKMNPRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
Oscar E Capuay Uceda
254
Seguridad Web
//indicar la cantidad de caracteres que tendr la palabra del CAPTCHA
$cantidad=6;
for($i=1;$i<=$cantidad;$i++) {
$pos = mt_rand(0,strlen($caracteres)-1);
$palabra.= substr($caracteres,$pos,1);
}
// comprobamos la existencia de la funcin ImageTTFText()
$fontsList = array(
"./fonts/VeraMoBd.ttf",
"./fonts/VeraMoBI.ttf",
"./fonts/VeraMono.ttf",
"./fonts/VeraMoIt.ttf"
);
$randFontNo = mt_rand(0, sizeof($fontsList)-1);
$randFontPath = realpath($fontsList[ $randFontNo ]);
// al azar las seales al fondo del respectivo texto ImageTTFText
for($i=1;$i<20;$i++){
$x
= mt_rand(0, 250); // pos x
$y
= mt_rand(0, 100); // pos y
$car = chr(mt_rand(45, 250)); //caracter aleatorio
$angulo = mt_rand(3,180);
imagettftext($imagen, 12, $angulo, $x, $y, $color_basura,
$randFontPath, $car);
}
// imprimir la palabra
$x = mt_rand(10,120);
$y = mt_rand(40,65);
imagettftext($imagen, 28, mt_rand(-10,10), $x, $y, $color_texto,
$randFontPath, $palabra);
//ensuciamos la imagen con lneas
for($i=1;$i<60;$i++){
$x = mt_rand(0, 250);
$y = mt_rand(0, 100);
imageline($imagen, $x, $y, $x+mt_rand(-40,40), $y+mt_rand(40,40), $color_basura);
}
// enviamos mediante la sesin la palabra elegida
$_SESSION["oculto"] = $palabra;
// enviamos la cabecera correspondiente al navegador y luego la imagen
header("Content-type: image/png");
imagepng($imagen);
// eliminamos la imagen
imagedestroy($imagen);
?>
255
Seguridad Web
Resultados Web:
Podemos ver a continuacin varios ejemplos de los CAPTCHAs generados.
256