Mostrando entradas con la etiqueta JQuery. Mostrar todas las entradas
Mostrando entradas con la etiqueta JQuery. Mostrar todas las entradas

lunes, 1 de octubre de 2012

Prevención de XSS (Cross-site scripting)

Dejo a disposición un pequeño ejemplo de como evitar del lado del cliente, haciendo la aclaración de que no debemos omitir la validación del lado del servidor, un ataque de seguridad usando el Cross-site scripting (XSS).

Esta vulnerabilidad se da cuando una aplicación web toma datos que el usuario suministra y los despliega en una página HTML. Si el usuario suministra datos que contiene caracteres que son interpretados como parte de un elemento HTML en lugar de texto literal, entonces un atacante puede modificar el HTML que es recibido por el navegador de la victima.

Para poder explotar esta vulnerabilidad, un usuario malicioso debe engañar a una victima para que visite un URL con la carga de XSS. Una carga de XSS puede consistir de HTML, JavaScript u otro tipo de contenido que pueda ser interpretado en el navegador. 

Este tipo de ataque apunta a usuarios de una aplicación web, en lugar de la aplicación web misma. Puede llevar al robo de credenciales de usuario e información financiera personal.

En el siguiente script recorro todos los elementos del formulario para reemplazar los paréntesis angulares ("<>") por sus códigos HTML equivalentes. Repito que este filtro debe aplicarse también del lado del servidor, pues un atacante podría crear un formulario propio sin estas validaciones y redirigir a una victima a esta versión maliciosa del formulario.

<html>
<head>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
 <script type="text/javascript">
 $(document).ready(function() {
   $('#formId').submit(function() {    
  var $inputs = $('#formId :input');    
  var values = {};
   $inputs.each(function() {
    var newValue=$(this).val().replace("<", "&lt;").replace(">", "&gt;");  
    $(this).val(newValue);
   });
  });
 });
 </script>
 </head>
<body>
 <form id="formId" action="sucess.html" method="get">
  user:<input type="text" name="username" />
  Password:<input type="password" name="password" />
  <input type="submit" />
 </form>
</body>
</html>

viernes, 14 de septiembre de 2012

Carga selectiva de JavaScript acorde con el Navegador

Interesante problema para resolver. Una funcionalidad de una página especifica no funciona apropiadamente en Chrome al parecer por la versión 1.7 de JQuery. La solución más sencilla es actualizar el sitio con la versión 1.8. Sin embargo por razones de tiempo y presupuesto, cambiar la versión de JQuery involucra probar el sitio de nuevo para validar que ninguna otra funcionalidad con dependencias de JQuery no se vieron afectadas.

La solución planteada entonces es cargar la versión 1.8 solamente en esa página, únicamente cuando el usuario usa el navegador Chrome. Para lograr esto hice un experimento primero (valga la nota de que deben haber soluciones más elegantes a esta) de colocar ambas versiones de JQuery en el HEAD para validar cuál versión de JQuery se utiliza si las dos están cargadas en la página. Algo así como determinar cuál es el orden de precedencia cuando hay funciones repetidas en dos scripts. Al parecer se invoca la última versión que se declara en el código.

Validado este experimento, programé un pequeño código, que con la ayuda de Yepnope, inyecto la versión 1.8 de JQuery cuando el navegador es Chrome.


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
 <script src="yepnope.1.5.4-min.js" type="text/javascript"></script>
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript"> 
 $(document).ready(function() { 
  $.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase()); 

  if($.browser.chrome){
   yepnope.injectJs("http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js", function () {
    alert ("JQuery Version: " + $().jquery);
   });   
  } else {
   alert ("JQuery Version: " + $().jquery);
  }
 });  
</script>
</body>
</html>

Corremos el script en FireFox:


Corremos el Script en Chrome:

lunes, 23 de julio de 2012

CakePHP: Carga dinámica de select input con JSON

Continuando con mis experiencias en este aprendizaje del framework CakePHP, quiero poner a disposición una receta en la cual tardé bastante en encontrar y personalizar, de cómo preparar una carga dinámica de un select box a partir de una selección anterior.

En este ejemplo cargo las opciones de raza a partir de una selección previa de una especie.

Ingredientes:


1. Función en el controlador para listar las especies (primer select box):

public function add() {  
   if ($this->request->is('post')) {
       // Código para salvar el anuncio.
    } else {
        $especie = new Especie();         
        $especies = $especie->find('list', array(       
     'fields' => array('Especie.id', 'Especie.nombre')
 ));
        $this->set('especies', $especies);         
    }
}

2. Código del formulario:
Form->create('Anuncio');
 
 echo $this->Form->input('especie', array(
     'type'    => 'select',
     'options' => $especies,
     'empty'   => 'Elija una especie'
 ));
 echo $this->Form->input('raza', array(
     'type'    => 'select',
     'empty' => 'Elija una especie'
 ));    
 echo $this->Form->end('Guardar Anuncio');
?>

3. Función en el controlador para retornar un JSON con las razas pertenecientes a la especie:

    public function getRazasByEspecie() {
     if ($this->request->is('ajax')) { 
      $idEspecie = $this->params['data']['idEspecie'];
       
      $raza = new Raza();
      $razas = $raza->find('all',array(
       'fields' => array('Raza.id', 'Raza.nombre'), 
       'conditions'=>array('Raza.id_especie'=>$idEspecie)));
      
      $this->RequestHandler->respondAs('json');
      $this->autoRender = false;      
      echo json_encode ( $razas );      
     }
    }

Preparación:

Agregar el código JavaScript que una (binding) la siguente lógica al evento de modificación del primer select box. La función hace un llamado Ajax al controlador para pedir las razas. Estas son retornadas en formato JSON el cual es procesado para agregar las nuevas opciones del segundo select box.
$(document).ready(function(){

 $('#AnuncioEspecie').change(function(){
  var selected = $(this).val();
    
  $.ajax({
   type: "POST",
   url: '/Anuncios/getRazasByEspecie',
   data: "idEspecie="+selected,
   dataType: 'json',
   success: function(data){
    
    $('#AnuncioRaza option').remove();
    var $el = $("#AnuncioRaza");
    if (data.length > 1) {
     $el.append($("")
       .attr("value", -1).text("Elija una raza"));
    }
    $.each(data, function(i,items){
     $el.append($("")
       .attr("value", items.Raza.id).text(items.Raza.nombre));          
    });    
   }
  });
 });
});


Consumase al gusto :D!

jueves, 2 de febrero de 2012

Pasando selección entre formularios con JavaScript

Hace poco tuvimos que resolver un problema algo trivial pero que hasta ahora me había tocado resolver. Consiste en poder seleccionar un valor de un "dropdown list" en una página con un formulario, y que ese mismo valor se seleccione en otra página con otro formulario pero con el mismo "dropdown list". Todo con puro código HTML y JavaScript.


La solución propuesta, a sabiendas de que pueda existir otra mejor, consiste en utilizar el método GET en el primer formulario.

<form method="get" action="part-b.html">
<select name="perro">
<option value="">Seleccion un perro...</option>
<option value="boxer">Boxer</option>
<option value="pastor">Pastor Aleman</option>
</select>
<input type="submit" />
</form>

De esta manera podemos leer el query string con una función que ya he utilizado varias veces, extraemos el parámetro y usamos una sentencia "abra kadabra" de JQuery para seleccionar el "dropdown list" con el parámetro.
<html>
<head>
<script src="jquery.min.js"></script>
<script type="text/javascript">
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
</script>
</head>
<body>

<form method="get" action="d.html">

<select name="perro" id="perros">
<option value="boxer">Boxer</option>
<option value="pastor">Pastor Aleman</option>
</select>
<input type="submit" />
</form>

<script type="text/javascript">
var perro = getUrlVars()["perro"];
$('#perros option[value=' + perro + ']').attr("selected", "selected");
</script>
</body>
</html>

viernes, 2 de diciembre de 2011

JQuery: Notas

Voy a mantener esta entrada activa como cuaderno de notas de JQuery.

Check Boxes

Saber si un checkbox está chequeado:
var isChecked = $('#myCheckBox').attr('checked');

Chequear/deschequear:
$('#myCheckBox').attr('checked', true|false);


Validaciones de formularios

Determinar si un campo de texto está vacío:

if($('#input_text').val().length == 0) {
// Empty field.
}

lunes, 2 de mayo de 2011

JQuery: Leer un XML y asignarlo a un arreglo asociativo

(In English: "Read XML into an associative array with JQuery")

Dejo a la disposición un pequeño ejemplo para leer un XML y asignar los datos a un arreglo asociativo de JavaScript (en dos dimensiones) usando JQuery.

Este es el XML de ejemplo:
<catalog>
<cd id="cd-001">
<param name="title" value="Empire Burlesque" />
<param name="artist" value="Bob Dylan" />
<param name="country" value="USA" />
<param name="company" value="Columbia" />
<param name="price" value="10.90" />
<param name="year" value="1985" />
</cd>
<cd id="cd-002">
<param name="title" value="Hide your heart" />
<param name="artist" value="Bonnie Tyler" />
<param name="country" value="UK" />
<param name="company" value="CBS Records" />
<param name="price" value="9.90" />
<param name="year" value="1988" />
</cd>
<cd id="cd-003">
<param name="title" value="Greatest Hits" />
<param name="artist" value="Dolly Parton" />
<param name="country" value="USA" />
<param name="company" value="RCA" />
<param name="price" value="9.90" />
<param name="year" value="1982" />
</cd>
</catalog>

Y el código HTML/JQuery:
<html>
<head>
<title>XML into associative array with JQuery</title>
<script type="text/javascript" src="jquery-1.5.2.min.js"></script>
<script type="text/javascript">
var cdArray = new Array(); // Will hold the XML data.

// Request to XML.
$.ajax({
type: "GET",
url: "cd-catalog.xml",
dataType: "xml",
async: false,
success: readXMLIntoArray
});

/**
Move XML data into associative array.
*/
function readXMLIntoArray(xml) {
$(xml).find('cd').each(function(){
var id = $(this).attr('id');
var parametersArray = new Array();
$(this).find('param').each(function(){

var name = $(this).attr('name');
var value = $(this).attr('value');

parametersArray[name] = value;
});
cdArray[id] = parametersArray;
});
}

// Testing array
document.write("<p>Title:" + cdArray["cd-002"]["title"] + "</p>");
document.write("<p>Artist:" + cdArray["cd-002"]["artist"] + "</p>");

</script>
</head>
<body>
</body>
</html>

Salida:

Title:Hide your heart

Artist:Bonnie Tyler