Intercambio de passwords en ASP.NET

A veces para depurar nuestra aplicación necesitamos entrar «como si fuésemos» otro usuario. Si utilizamos la seguridad de formularios de ASP.NET la información de usuarios se guardará normalmente en una base de datos de SQLServer. Por seguridad la contraseña de los usuarios no se guarda en la BBDD, sino que se guarda un hash que nos sirve para saber si el usuario ha metido la contraseña correcta.

La forma menos intrusiva y más sencilla que tenemos de autenticarnos como otro usuario, es copiar nuestro password en el suyo. Para ello debemos de copiar dos campos de la tabla aspnet_Membership: Password y PasswordSalt. Para encontrar cuál es el usuario tenemos también que acceder a la tabla aspnet_Users, en donde podemos buscarlo por UserName. Y al acabar de hacer las pruebas estaría bien dejar todo como estaba, así que lo ideal sería haber guardado la información original en algún sitio.

El siguiente script hace todo esto por nosotros: intercambia la contraseña de dos usuarios, definidos por sendos parámetros al principio. De esta forma si quiero hacer una prueba en mi aplicación con el usuario ‘admin’, basta con que ejecute el script, entre con mi contraseña y el usuario ‘admin’ y finalmente vuelva a ejecutar el script para intercambiar de nuevo las contraseñas y dejar todo como estaba.

declare @Usuario1 varchar(250),@Usuario2 varchar(250);
--Datos de prueba
select @Usuario1='miUsuario',@Usuario2='admin';

begin
tran
    --Guardo la informacin del usuario1 y 2
   
select U.UserName,M.UserId,M.ApplicationId,M.Password,M.PasswordSalt
   
into #infoUsuario
   
from aspnet_Users U
   
inner join aspnet_Membership M
   
on U.UserId=M.UserId and U.ApplicationId=M.ApplicationId
   
where U.UserName=@Usuario1 or U.UserName=@Usuario2;

    --Intercambio las informaciones
   
update aspnet_Membership
   
set [Password]=n.[Password], PasswordSalt=n.PasswordSalt
   
from
   
(--Consulta que hace el verdadero swap
       
select A.UserName, A.UserId,A.ApplicationId,B.Password,B.PasswordSalt
        from
#infoUsuario A,#infoUsuario B
       
where A.UserId<>B.UserId
   
) n
   
where
    aspnet_Membership
.ApplicationId=n.ApplicationId
   
and aspnet_Membership.UserId=N.UserId;

    --Borrado de la tabla temporal
    if(OBJECT_ID('tempdb..#infoUsuario') is not null)
   
    drop table #infoUsuario;
commit tran

 

Fíjate que la base de datos de membership puede ser compartida por varias aplicaciones de asp.net, de ahí que introduzca en la consulta el campo ApplicationId. Si tienes esta información en tu base de datos exclusiva para la aplicación puedes obviar esta condición.

¿Sencillo, no?

Doodle K

Estos días está todo el mundo conjeturando acerca de las intenciones y significados de los últimos doodels. Más allá de sus motivos (supongo que hacer ruido) el efecto es cuánto menos curioso y muy sencillo de replicar:

¿Cuál es el truco? No hay Flash, ni Silverlight ni nada complicado detrás de este efecto: simplemente tenemos dos divs con su background establecido a la misma imagen, una de ellas en color y la otra en gris. El único truco de este efecto es una función de javascript que responde al evento onkeyup(this.value.length) que envía el número de caracteres del cuadro de texto para redimensionar el div que contiene la imagen en color.
 
function SetFrontWidth(value)
{
    var div1=document.getElementById(‘divK’);
    var longitud=Math.round(700*value/6);
    if(longitud>580)
        longitud-=20;
    div1.style.width=longitud;
}

Para más detalle se puede bajar el código completo de este ejemplo (no utiliza css ni código externo alguno).

 

¿Por qué cambiar IsNull por Coalesce?

IsNull es la función de Sql Server que la mayoría de los programadores que llevan unos años escribiendo consultas utilizan. Su función es devolver un valor por defecto si el primer argumento pasado es nulo.

Por ejemplo, supongamos que tenemos la siguiente tabla:

declare @Clientes as table (Id int, Nombre varchar(100));

 Y queremos actualizar un campo determinado, por ejemplo el Id=2, para que el nombre coincida con un parámetro que nos pasarán desde programa. Entonces la consulta a ejecutar sería tan sencilla como esta:

update @Clientes set Nombre = @NuevoNombre where Id=2;

Ahora  queremos mejorar nuestra consulta, de forma que si el parámetro @NuevoNombre es nulo la fila no se actualice y mantenga su valor. Entonces podríamos substituir la segunda línea por cualquiera de estas dos opciones:

        a) set Nombre=IsNull(@NuevoNombre,Nombre);

        b) set Nombre=Coalesce(@NuevoNombre,Nombre) 

 Siempre que el parámetro esté correctamente definido ambas consultas se comportarán igual. El problema viene cuando el parámetro (por ejemplo por utilizar inferencia en el sistema de origen) viene con una definición distinta. Imaginemos por ejemplo que definimos así el parámetro y ejecutamos la consulta:

declare @NuevoNombre as varchar(2)= null;

En el update con calesce el resultado es el esperado, mientras que en el caso de IsNull, la tabla se actualizará incorrectamente. Esto es debido a que realmente IsNull no devuelve el segundo parámetro, sino el resultado de convertir el valor del segundo parámetro al tipo del primero, lo cual consituye una diferencia fundamental.

A continuación listamos el código completo para copiar y pegar y demostrar el funcionamiento. Basta con descomentar alternativamente uno u otro UPDATE para comparar los resultados.

declare @Clientes as table ( Id int, Nombre varchar(100));
insert into @Clientes values
    (1,'Francisco Otero'),
    (
2,'Otro fulano');

declare @NuevoNombre as varchar(2)=null;
--update @Clientes
--set Nombre= @NuevoNombre
--where Id=2

--update @Clientes
--set Nombre=Coalesce(@NuevoNombre,Nombre)
--where Id=1

select * from @Clientes;