Quantcast
Channel: Planeta Código
Viewing all 2699 articles
Browse latest View live

Mascando Bits: Cambiar de Branch en un Shallow Clone

$
0
0

Si estas usando sistemas de integración continua (Continuous Integration), trabajas con repositorios pesados o simplemente no quieres pasar por un un clonado de Git que te traiga todo el árbol de un repositorio, seguro que estás familiarizado con el concepto shallow clone o clonado superficial.

Un shallow clone o cloando superficial permite traerse los últimos commits y no todo el histórico del repositorio Git. Aunque pueda parecer una solución maravillosa para desprenderse de los problemas de un clonado completo del histórico del árbol Git , presenta ciertos problemas a la hora de operarlo como un repositorio clonado de manera normal cuando se ha clonado bajo estas condiciones específicas de clonado.

🐑 Crear un clonado superficial

Para ejecutar un clonado superficial o shallow clone lo haremos con el siguiente comando:

git clone -–depth [depth] [remote-url]

Donde depth la profundidad es el número de commits que nos vamos a traer durante el clonado y remote-url es la dirección URL de origen de donde vamos a clonar el repositorio. 👀 El uso de --depth implica --single-branch.

Para ejecutar clonado superficial o shallow clone de una rama o branch podemos hacerlo con:

git clone [remote-url] -–branch [name] -–single-branch

Donde name es el nombre de la rama o branch que queremos clonar.

Si aún queremos hilar más fino y resulta que tenemos repositorios con submódulos (repositorios Git incluidos en otro repositorio), los cuales tienes su propio árbol Git y se inicializan usando alguno de los siguientes comandos:

git clone -–recursive [remote-url]  # Git version >= 1.6.5
git clone -–recurse-submodules -–jobs [num-jobs] [remote-url]   # Git version >= 2.13

La primera sintaxis con recursive puede resultar más cómoda, aunque resulta más rápida y eficiente la segunda con recurse-submodules, la cual es la sintaxis vigente que permite especificar el número de submódulos operados concurrentemente mediante jobs.

Si este es tu caso, no tiene sentido hacer un clonado superficial si se hace un clonado completo de los submódulo. Para ello ejecutaremos el siguiente comando:

git clone -–depth [depth] -–shallow-submodules [remote-url]

La opción --shallow-submodules implica que todos los submódulos se clonarán con una profundidad de 1.

🐏 Convertir un repositorio con clonado superficial en uno de tipo clonado completo

Si has seguido los pasos anteriores, te darás cuenta que si quieres cambiarte por ejemplo a otra rama no puedes. Eso es debido a que se ha omitido el resto del histórico según se lo hemos especificado. ¿Eso significa que no existe? No, eso sólo quiere decir que no lo conocemos.

Si ejecutamos el siguiente comando sobre un repositorio clonado superficialmente, veremos los remotos que conocemos y los remotos existentes en el local:

git branch -–all

Si intentamos hacer un fetch del remoto veremos que tampoco conseguimos ver el histórico completo del responsorio:

git fetch -–verbose

Esto es debido a que nuestro remoto no está convenientemente configurados debido al clonado superficial. Podemos restaurar su funcionalidad completa partiendo de que nuestro remoto origin, de donde clonamos el repositorio, contiene la remote -url que metimos. Por ello podemos restaurar el acceso a todo el histórico del remoto para nuestro repositorio, usando el siguiente comando:

git remote set-branches origin '*'

Mediante la opción set-branches podemos cambiar la lista de ramas que son seguidas por el remoto conocido y por defecto que es origin.

Ahora volvemos a ejecutar el comando fetch de nuevo y en este caso podremos apreciar que la totalidad de ramas aparecen:

git fetch -–verbose

Con esto ya tenemos acceso al historial completo del repositorio y podermeos cambiarnos a otra rama a la cual antes no podíamos:

git checkout rama-que-estaba-buscando

Si quieres comprobar el último commit de la rama local para cotejarlo con el último commit disponible el remoto y comprobar que está todo correcto, puedes hacerlo con:

git show

💡 Conclusiones

El clonado superficial o shallow clone es una gran herramienta, pero puede echarnos el lazo al cuello si no sabemos y necesitamos deshacerlo. No obstante aunque siempre existe la opción de hacer un clonado clásico de nuevo, no resulta una opción elegante y eficiente que nos obliga a duplicar y volver a clonar el repositorio.


Blog Bitix: Medidas de seguridad a implementar para prevenir y minimizar daños en ataques informáticos

$
0
0

Los ataques informáticos dirigidos a los usuarios tienen el objetivo con una motivación económica del delincuente de robarles las credenciales de sus cuentas, datos de tarjetas de crédito y datos personales, otros ataques están dirigidos a los servicios que usan los usuarios. De los ataques dirigidos a los usuarios implementando las medidas de seguridad adecuadas en el servicio varios tipos de ataques son evitables como el phishing que es uno de los más comunes ofreciendo inicio de sesión con segundo factor de autenticación y con otras medidas los daños y riesgos son limitables. Otras medidas de seguridad implementadas en el servicio evita riesgos como usar salted pasword hashing. Como programadores los servicios deben hacer uso de buenas prácticas e implementar medidas adicionales para evitar riesgos y daños.

Algunos ataques informáticos están dirigidos a las empresas y sus sistemas de computación explotando alguna vulnerabilidad de seguridad. Tener un fallo de seguridad ya de por sí es un grave problema para la imagen de la empresa también con consecuencias económicas de pérdida de clientes o valor en la bolsa sino también legales con posibles cuantiosas multas , además de otras consecuencias intangibles como la reputación entre sus clientes y usuarios.

Otros ataques están dirigidos hacia los usuarios como el robo de datos personales, bancarios o credenciales con técnicas de suplantación de identidad o phishing. Aún hoy en día muchas personas apenas tienen unos conocimientos básicos de tecnología y la mayoría desconoce las medidas básicas de seguridad. Estas personas aún con una alfabetización digital muy básica están rodeadas de tecnología y realizan importantes tareas como compras y transacciones bancarias. Muchas personas son víctimas de fraudes y estafas por internet, a veces por su desconocimiento pero también a veces porque las empresas no implementan medidas de seguridad suficientes para que sus servicios sean más difícil de ser explotados.

Los informáticos tenemos una gran responsabilidad para diseñar sistemas seguros aplicando las mejores prácticas de seguridad no solo como algo adicional a la finalización de una funcionalidad, sino involucrando al rol de security operations o SecOps desde el inicio, al igual que no se deben dejar las pruebas de aseguramiento de calidad para el final la seguridad tampoco debería. Los bancos utilizan medidas adicionales para realizar operaciones pero algunas medidas de seguridad dejan que desear en varios aspectos como requerir para todas las cuentas bancarias iniciar sesión en la banca online con el número del DNI y un código de seis dígitos, no implementar medidas de notificación de pagos, transferencias o falta un registro de actividad completo en la cuenta digital.

Sin embargo, me da miedo que un banco que debería ser un referente en medidas de seguridad incluyan en la página donde los usuarios introducen sus credenciales para el acceso a la banca online recursos JavaScript de Facebook, Twitter y de dominios ajenos al banco que no controlan para hacer analítica web de seguimiento de usuarios.

Contenido del artículo

Inyección de SQL, XSS, tabnabbing y otras vulnerabilidades básicas

Hay errores de seguridad comunes identificados hace ya tiempo que aún no están obsoletos, no son errores de seguridad complejos de explotar y tampoco son errores complejos de evitar usando las técnicas adecuadas de programación o evitando utilizar ciertas operaciones en la manipulación de datos. Varios de los errores de seguridad son por usar datos provenientes de fuentes no confiables sin aplicar el tratamiento adecuado. Aún siendo errores simples son peligrosos en una aplicación vulnerable.

La fundación OWASP mantiene un registro detallado de los diferentes tipos de seguridad, explicando el problema de seguridad y cómo evitarlos. También publicar cada ciertos años una lista de los 10 errores más comunes durante ese año.

Salted Password Hashing

Una aplicación que guarda credenciales para autenticar a los usuarios habitualmente solicita dos datos, un identificador del usuario o de la cuenta y una contraseña que como solo conoce el legítimo usuario permite identificarle en el sistema al iniciar sesión. Los identificadores de los usuarios y las contraseñas la aplicación necesita guardarlas en una base de datos para que la aplicación las compare con las que proporciona un usuario al iniciar sesión.

Guardar la contraseña en la base de datos el valor original que el usuario ha proporcionado es un peligro ya que cualquier persona con acceso a la base de datos es capaz de conocer el valor de la contraseña. Para no guardar el valor original es posible utilizar una función de hash de un solo sentido que permite transformar el valor original en otro derivador a partir del cual no es posible conocer el valor original pero permite conocer si es válido aplicando la función al dato proporcionado y comparándolo con el guardado en la base de datos. Sin embargo, usar una función hash no es suficiente ya que utilizando un ataque de diccionario con valores precalculados de hashes de valores comunes de contraseñas permite identificar cuentas con contraseñas débiles.

La forma correcta de guardar contraseñas es utilizando cifrado o sin cifrado utilizando una versión modificada de hash denominada salted password hashing que evita ataques de diccionario.

Implementación de segundo factor de autenticación

Muchos usuarios no tienen conocimientos de informática, ni una alfabetización digital avanzada. Estos usuarios con unos conocimientos mínimos utilizan la tecnología por ser necesaria ya para muchas tareas o permitir realizarlas de forma más rápida y sencilla. Pero incluso usuarios con muchos conocimientos avanzados de tecnología también son vulnerables a ciertos tipos de ataques como los de phishing sin las precauciones adecuadas. Los ataques de suplantación de identidad o phishing son empleados por los delincuentes para robar información personal, credenciales de acceso a cualquier tipo de servicio y datos bancarios como tarjetas de crédito.

Las aplicaciones que ofrecen el segundo factor de autenticación y los usuarios que lo emplean mantienen su cuenta a salvo incluso si son víctimas de un ataque de phishing. Con el segundo factor de autenticación además de la contraseña que es el algo que solo el usuario sabe se requiere algo que se tiene que sería un generador de códigos temporales. En un ataque de phishing los delincuentes se hacen con lo que se sabe, si esto es lo único que permite el acceso a una cuenta es suficiente para que los delincuentes accedan a ella. Con el segundo factor de autenticación la contraseña no es suficiente se requiere un código adicional, en caso de que un ataque de phishing robase el código temporal sólo permitiría iniciar sesión en la cuenta durante un breve periodo de tiempo habitualmente de 30 segundos.

Los servicios más conocidos implementan el segundo factor de autenticación que los usuarios deben activar, no es difícil de implementar en Java.

Notificación de acciones relevantes

Algunas operaciones son relevantes desde el punto de vista de seguridad, como el inicio de sesión, un intento fallido de inicio de sesión, cambio de contraseña o realización de algunas operaciones en el ámbito de la aplicación. Para mejorar la seguridad conviene enviar en este tipo de acciones una notificación al usuario que permita advertir ante acciones que se puedan realizar sin su conocimiento. Las notificaciones permiten al usuario tomar medidas en caso de que detecte acciones fraudulentas. Las notificaciones pueden ser a través de un correo electrónico, mensaje SMS o a través de mensajería instantánea.

Estos son dos ejemplos de correos electrónicos que envía Gmail y Wallapop para notificar al usuario de un nuevo inicio de sesión en su cuenta.

Notificación de Gmail de inicio de sesiónNotificación de Wallapop de inicio de sesión

Correos electrónicos de notificación de inicio de sesión

Registro de actividad

Mantener un registro de la actividad es otra variante para dar visibilidad y permitirle al usuario identificar actividad fraudulenta en su cuenta en caso de que haya sido víctima de un ataque o sus credenciales hayan sido robadas. Algunos servicios mantienen un registro con las fechas de los últimos inicios de sesión, la dirección IP de la computadora junto con su geolocalización que permite conocer su ubicación aproximada, el navegador usado, sistema operativo o fecha de últimos cambios de contraseña.

Registro de actividad en una cuenta de Gmail

Registro de actividad en una cuenta de Gmail

Establecer límites de uso

Ya sea por una fallo de seguridad en un servicio vulnerable que ha sufrido un ataque o por un ataque dirigido al usuario por ejemplo con un ataque de phishing es posible implementar medidas no dirigidas a evitar los ataques sino a mitigar o reducir los posibles daños de un posible ataque.

Para mitigar los posibles daños un servicio puede implementar medidas para limitar los datos como establecer un límite de intentos fallidos de inicio de sesión antes de bloquear la cuenta de forma temporal. Los bancos por ejemplo permiten activar o desactivar las tarjetas de crédito a petición del cliente que impidan la autorización de operaciones, con esta medida aunque un usuario haya sido atacado y un delincuente haya robado los datos de su tarjeta de crédito este puede desactivarla para evitar operaciones fraudulentas con ella unido a la notificación de acciones relevante un usuario puede actuar para evitar más daños. Otras medidas que utilizan los bancos son establecer límites de disposición de efectivo diario, importe máximo de transferencias, importe máximo en comercios físicos y electrónicos y de compras por internet.

Cifrar información personal

Los datos personales están protegidos por leyes, un fallo de seguridad con el resultado de robo de datos personales también tiene consecuencias legales para la empresa con importantes multas y económicas por pérdida de clientes y mala imagen.

Los datos a proteger de los usuario son aquellos que permita identificarlos como nombre y apellidos, DNI, dirección de correo electrónico, dirección del domicilio, número de teléfono y por supuesto datos bancarios como número de cuenta y tarjetas de crédito.

Para evitar el riesgo de un ataque dirigido al servicio que ocasione una fuga de datos es conveniente cifrarlos. Incluso para que los empleados que trabajan en la empresa no conozcan a quién corresponden esos datos.

Cifrados los datos aun teniendo acceso a ellos la información está protegida ya que es necesario descifrarlos para obtener el valor original.

Vault es una aplicación que ofrece el cifrado como servicio entre otras funcionalidades de seguridad.

Informar a los usuarios

Para prevenir fraudes otras medidas sencillas son informar a los usuarios de unas medidas básicas de prevención de fraude y explicar cómo son los procedimientos de comunicación.

Algunos son desconfiar de mensajes inesperados, no acceder a enlaces de mensajes SMS, de mensajería instantánea y leer con atención la dirección en el navegador de los enlaces a los que se acceder.

Nunca facilitar datos personales, credenciales de acceso a una cuenta no datos de tarjetas bancarias. Tampoco descargar ni instalar aplicaciones si no provienen de las tiendas oficiales del dispositivo. Y activar las notificaciones para conocer la actividad en la cuenta del servicio.

Comunicaciones entre servicios

La arquitectura de las aplicaciones tienden a diseñarse de forma que ofrezcan un medio de invocar sus funcionalidades mediante llamadas de red ya sea con el protocolo HTTP mediante REST, GraphQL o gRPC.

Para autorizar las llamadas a los servicios estos han de implementar alguna forma de autenticación y autorización por ejemplo con OAuth y JWT.

Otra forma de proteger los servicios más sencilla sin que cada uno de ellos tenga que implementar las funcionalidades de autenticación y autorización es utilizar un service mesh. Consul además de ser un servicio que ofrece registro y descubrimiento ofrece la funcionalidad de conexión entre servicios con cifrado, autenticación mutua y autorización especificando qué servicio está autorizado a comunicarse con cual.

Con las funcionalidades de conexión de Consul los servicios no es necesario que implementen el cifrado, autenticación y autorización. Los servicios tienen menos responsabilidades, son más sencillos y la autorización de la comunicación es gestionada desde Consul.

Contraseñas en repositorios de código fuente y artefactos compilados

La seguridad de las aplicaciones se basa en contraseñas, claves privadas y certificados que únicamente las aplicaciones y los administradores de los servicios deben tener acceso.

Las credenciales deben ser guardadas aparte del código fuente de la aplicación, fuera de la herramienta de control de versiones. Incluso las credenciales en una clase Java compila a bytecode es posible acceder a ellas.

Estos secretos deben proporcionarse a las aplicaciones en tiempo de ejecución por el orquestador de procesos, el entorno de ejecución en la nube o de un servicio específico de seguridad del que obtenerlo. Para mayor seguridad las propiedades con secretos de los archivos de configuración en el sistema de archivos deben evitarse.

Otras

Otra medida de seguridad es ofrecer la posibilidad de eliminar una cuenta o desactivarla tras un periodo de inactividad prolongado.

info.xailer.com: TinyMCE El más completo editor de textos HTML y ahora en aplicaciones de escritorio Xailer, ¿por que no?

$
0
0

Para los que seguimos creyendo firmemente que a las aplicaciones de escritorio les queda una larga vida, vemos que la Web está bien para depende que, pero no vemos aún a nuestros clientes realizando sus ventas de fruta conectadas a una báscula serie desde la web o realizando su facturación o su contabilidad desde la nube, bien sea por velocidad, inmediatez, sencillez o por costumbre simplemente.

Pero a todos nosotros, desarrolladores de aplicaciones de escritorio, nos llama poderosamente la atención la riqueza gráfica de los componentes que hay para la Web, auténticas maravillas que por ejemplo permiten hacer graficas multi formato, coloridas y con movimiento.

Y fue uno de estos componentes el que me impactó en cuanto lo vi funcionando dentro de la mayor parte de las Web hechas con WordPress y no es otro que un completo procesador de textos online llamado TinyMCE    https://www.tiny.cloud tan completo que casi todas esas Web sustituyen el nativo de WordPress por éste. TinyMCE es multi idioma y totalmente parametrizable para tener el diseño a tu gusto.

Internet está lleno de demos, ejemplos, videos de Youtube como éste, que muestran todo su increíble potencial, tanto que te hará olvidar a Word. Puedes manejar imágenes, recortarlas y girarlas, manejar tablas de datos con gran complejidad, etc. casi todo lo que se te ocurra y encima es un complemento gratuito, aunque también hay una versión comercial más completa, pero la básica es más que suficiente.

Hace tiempo que empezamos a desarrollar aplicaciones WEB como complemento de nuestras aplicaciones de escritorio, de forma que los clientes puedan tener en su bolsillo ciertas utilidades, consultas o resultados de sus aplicaciones de escritorio y para ello empezamos a trabajar con Nefele 4 Harbour    https://www.nefele.dev   
Esto nos abrió un universo de posibilidades en la Web y pudimos salir del escritorio, sin dejar de trabajar con el entorno Xailer y el lenguaje Harbour que conocemos y en el que nos sentimos tan cómodos, pero ahora para la Web.

La experiencia recogida en estas aplicaciones Web y la aparición del increíble componente Edge WebView en Xailer 7 nos llevó a preguntarnos si era factible llevar la Web al escritorio y nos pusimos manos a la obra, por que no meter TinyMCE en nuestras aplicaciones a través del WebView integrado. Dicho y hecho, en pocas horas estaba andando.

Ahora tenemos un procesador de texto que genera HTML con toda riqueza de detalles y que podemos grabar en un campo de una base de datos y leerlo desde este campo para mostrarlo de nuevo en pantalla, imprimirlo o casi lo que se quiera.

Adiós al triste campo Memo y adiós al RTF que ya ha cumplido años y tocaba jubilar, bienvenido TiNyMCE.

¿Que hace falta para integrarlo en nuestras aplicaciones Xailer?

1.- Creas un Form con un objeto WebView en su interior. Este ejemplo es nuestro redactor de correos electrónicos y el objeto Webview es el cuadro blanco inferior.

2.- Sobre éste objeto contenedor instancio un componente TinyMCE

WITH OBJECT ::oWebView
  With Object ::oTinyEditor := TTinyMCE( ):New( ::oWebView ) 
  End
END

Para ello debemos de contar con la CLASS TTinyMCE que hemos desarrollado y que se incluye en el proyecto Xailer que se adjunta y que puedes descargar desde el área de descargas de Xailer.

Esta clase permite de una forma muy simple parametrizar el aspecto, el menú, los botones y el funcionamiento del editor de textos como puede verse en su definición:

Property cLanguage         Init "esp"  //Opciones   esp, cat , eus, gal, mex
Property lButtonBar        Init .T.
Property lAllButtons       Init .T.    //Muestra una barra de botones con todas las opciones siguientes
Property cFormatButtons    Init "bold italic underline |"
Property cFormatExButtons  Init "formatselect  fontselect fontsizeselect | "
Property lColorButtons     Init .F.   
Property cColorButtons     Init "forecolor backcolor  |"
Property lAdjustButtons    Init .F.   
Property cAdjustButtons    Init "alignleft aligncenter alignright alignjustify |"
Property lNotepadButtons   Init .F.
Property cNotepadButtons   Init "cut copy paste|"
Property lUndoButtons      Init .F.
Property cUndoButtons      Init "undo redo|"
Property lBulletButtons    Init .F.
Property cBulletButtons    Init "bullist numlist outdent indent |"
Property lInsertButtons    Init .F.
Property cInsertButtons    Init "hr link insertfile | quickimage image | emoticons |"
Property lTableButtons     Init .F.
Property cTableButtons     Init "table |"
Property lSearchButtons    Init .F.
Property cSearchButtons    Init "searchreplace |"
Property lPrintButtons     Init .F.
Property cPrintButtons     Init "print export|"  //preview
Property lConvertButtons   Init .F.
Property cConvertButtons   Init "ConvertToWord |"
Property cOwnerButtons     Init ""     //Para construir una barra especial del control, se mostrarán los controles que aquí se citen
Property cDevelButtons     Init "|visualblocks code "  //Controles para el desarrollador permiten ver los bloques de texto del Html y editar el código fuente
Property cFontSizes        Init "6pt 8pt 10pt 12pt 14pt 18pt 24pt 36pt 72pt"
ACCESS   cSelectButtonbar  Inline ::cFormatButtons + ::cFormatExButtons + ::cColorButtons + ::cAdjustButtons
Property lAutoSave         Init .F.    //Mensaje de guardar antes de salir
Property lSpellChecker     Init  NIL   //Usar el corrector ortográfico de Edge
Property lStatusBar        Init .T.    //Mostrar la barra de estadoY listo, ya sale andando y puedes escribir el texto que quieras o incluso editar WebPages que puedes copiar y pegar desde internet.

3.- Pero como cualquier componente de Internet cada vez que lo invocamos irá a la Web a leer desde un CDN todo lo necesario para su funcionamiento, el código JavaScript, los iconos, etc. con lo cual necesitamos una conexión Internet y unos segundos de conexión. Pero esto puede evitarse si descargamos esta información y la metemos en una subcarpeta de nuestra propia aplicación, por ejemplo en el proyecto de ejemplo  .\Xtras\TinyMce  y de esta manera logramos independencia total de la Web y mayor velocidad de carga.

Pegas de TinyMCE.

La versión gratuita utiliza el corrector ortográfico del navegador del equipo y solo subraya los errores en el idioma en uso. Además el botón derecho no ofrece listas de correcciones, eso se reserva para la versión de pago.
Otra pega es que el botón de pegar desde el portapapeles parece no funcionar en ningún sistema, pero te lo dice y te invita a pulsar Ctrl+V que si funciona.

Y esto no es más que el principio de algo muy grande.

Imagina poder tomar controles de esos que se te cae la baba al verlos por Internet y poder integrarlos en tus aplicaciones de escritorio de forma nativa y sin necesidad de conectarte siquiera a la web.

Por ejemplo, este es un control de calendario https://fullcalendar.io.demos funcionando desde Xailer completamente en local contra una base de datos MariaDB.

Pero esto ya será para otro capítulo……

Descarga de ejemplo de uso

Variable not found: Enlaces interesantes 460

$
0
0
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin / MAUI

Otros

Publicado en Variable not found.

Header Files: Introducción a Boost.Log

$
0
0

Introducción

Un sistema de log es de una gran utilidad a la hora de localizar errores en nuestras aplicaciones de una forma rápida. Esto es especialmente cierto en código en producción, en donde normalmente no tenemos acceso a las herramientas habituales de depuración, o donde ni siquiera tenemos acceso al sistema en cuestión sino que dependemos de que el usuario nos diga o mande cosas.

El objetivo de un log es el de proporcionarnos información persistente sobre el estado del sistema en un punto dado, así como el flujo de ejecución que llevó hasta dicho punto. Adicionalmente, suele ser interesante poder contar con datos adicionales de diagnóstico como la configuración de la aplicación, características del ordenador, etc.

Cada entrada (o mensaje) del log suele contar con una marca de tiempo (timestamp), lo que nos permitie asociar sucesos entre módulos, además de poder saber con más certeza cuáles mensajes pertenecen a una misma acción y cuáles a otras.

Otro factor importante a tener en cuenta es que no todos los mensajes del log son siempre útiles: algunos nos dan información sobre configuraciones inválidas o errores del sistema, mientras que otros nos indicarán las llamadas a diferentes funciones. Estas segundas son útiles cuando se quiere encontrar un error, pero de normal suponen una sobrecarga innecesaria. Esto nos lleva a que es importante poder discriminar entre niveles de mensajes (normalmente llamada severidad del mensaje).

Por otro lado, es interesante contar con un log limpio por ejecución, de forma que sea fácil poder seguir los pasos del usuario. Además, normalmente no son útiles los logs antiguos, por lo que nuestra aplicación debería ser capaz de deshacerse de ellos automáticamente. A todo esto se le llama rotación.

¿Más en la lista a los Reyes Magos? Inspeccionar un log largo no es divertido, por no decir que difícil, así que cualquier ayuda viene bien. Una forma es guardar el log en un formato que nos permita su estudio: por ejemplo un XML correctamente etiquetado, de forma que podemos filtrar los mensajes por tipo, rango de tiempo, módulo. Otro podría ser un HTML que visualmente nos separe mensajes de información de errores.

Algo parecido podría decirse si queremos ver el log en tiempo real durante la ejecución del programa. Para ello se muestra el log por pantalla (consola, o una ventana separada). Esto permite activar una especie de modo depuración sin tener que recurrir a un debugger propiamente dicho (por no decir que a veces, como en aplicaciones concurrentes, abrir el depurador rompe el estado del sistema y no nos permite seguir correctamente la pista de un fallo).

Soluciones básicas

Obviamente no todo sistema de logging debe cumplir con todo los requisitos expuestos anteriormente, y un subconjunto puede perfectamente cubrir nuestras necesidades. Recuerdo uno que solía tener siempre a la mano un antiguo compañero de trabajo, y que podría resumirse en un pequeño fichero de cabecera tipo

#ifndef LOG_H
#define LOG_H
#include <iostream>
#ifndef NO_LOG
# define LOG(msg) std::cerr << msg << std::endl;
#else
# define LOG(msg)
#endif
#endif

Luego añadía variantes del LOG para diferentes niveles de severidad y estaba servido. No necesitaba más. Lo podía usar en desarrollo, y se podía sacar de cliente mandando una versión nueva del ejecutable y redirigiendo el error estándar a un fichero. No cumple con todo lo expuesto anteriormente pero sirve, es portable e incluso puede ser escrito sobre la marcha si se necesita. Si queréis ver la versión completa está disponible en el repositorio del miniLogger.

Boost.Log

Ahora bien, en este artículo quiero exponer una solución más completa. Usaré Boost.Log (boost::log), para no reinventar la rueda (bueno, al menos no toda la rueda). Como todos sabemos, Boost es uno de esos casi-inseparables de C++: mucho de lo que le falta a la biblioteca estándar se puede encontrar en Boost, hasta el punto que muchas de las nuevas adiciones a la biblioteca estándar toman como inspiración (o copia directa) a Boost.

Como muchas cosas en Boost, Boost::log es enorme y complejo, por lo que limitaré este artículo a introducir aquellas funcionalidades que encajen con los requerimientos arriba mencionados.

Namespaces

Para simplificar el código y hablar el mismo lenguaje, renombraremos algunos espacios de nombre y tipos:

namespacelogging=boost::log;namespaceexpr=logging::expressions;namespaceattrs=logging::attributes;namespacesinks=logging::sinks;namespacekeywords=logging::keywords;usingseverity_t=logging::trivial::severity_level;

Boost provee varias severidades por defecto bajo logging::trivial::severity_level: trace, debug, info, warning, error y fatal.

Uso básico

logging::sources::severity_logger<severity_t>log;BOOST_LOG_SEV(log,severity_t::info)<<"Message to show";

Normalmente se simplifica su uso mediante macros como

#define LOG_INFO() BOOST_LOG_SEV(log, severity_t::info)
#define LOG_DEBUG() BOOST_LOG_SEV(log, severity_t::debug)
// ...LOG_INFO()<<"Message to show";

Log a consola

Siendo la configuración más simple, comenzaremos por acá. Existen varias formas de configurar el log para mostrar los mensajes por pantalla, pero la más directa es mediante:

logging::add_console_log(std::cout,logging::keywords::format=formatter);

Donde formatter puede ser desde una simple cadena de formato tipo >> %Message%, a una función que lo haga. Optaremos por la segunda versión.

Función de formateo

Esta función recibe un registro del mensaje, con atributos como el mensaje, marca de tiempo, etc., y un stream al que escribir la entrada del log. Es en esta función donde podemos definir qué campos mostramos y cómo, formato del documento final (se usa el mismo tipo de función para consola que para fichero), coloreado, etc.

Abajo se muestra un ejemplo para un formateo de mensaje a mostrar por consola, con el formato [severity] timestamp: message. Cada mensaje además se colorea de una forma distinta dependiendo de su severidad para facilitar la lectura del mismo.

voidformatter(logging::record_viewconst&rec,logging::formatting_ostream&strm){strm<<">> ";// Severitystaticconstautos_severity_labels=std::vector<std::string>{"trace"s,"debug"s,"info"s,"warning"s,"error"s,"fatal"s,};staticconstautos_severity_colours=std::vector<std::string>{"\033[37m"s,"\033[32m"s,"\033[36m"s,"\033[33m"s,"\033[31m"s,"\033[37;41m"s,};autoseverity=rec[logging::trivial::severity];if(severity){if(static_cast<std::size_t>(severity.get())<s_severity_colours.size()){// Colorize based on severitystrm<<s_severity_colours[severity.get()];// Show severity aligning messagesstrm<<"["<<std::left<<std::setw(7)<<std::setfill(' ')<<s_severity_labels[severity.get()]<<"] ";}}// Timestamp and messagestrm<<rec[attr_timestamp]<<": "<<rec[expr::smessage];// Reset colorif(severity){strm<<"\033[0m";}}

Para el estilo visual en consola se han usado códigos ANSI/VT100.

Para el uso del timestamp es necesario definir el atributo en algún punto global:

BOOST_LOG_ATTRIBUTE_KEYWORD(attr_timestamp,"TimeStamp",attrs::local_clock::value_type)

Log a fichero

La configuración para guardar el log a fichero es algo más larga y conlleva crear un objeto backend con información como nombre de los ficheros de log y datos de rotación, y adjuntarlo a un objeto sink junto al formato del mismo.

autobackend=boost::make_shared<sinks::text_file_backend>(keywords::file_name=dir+"/"+prefix+"_%Y%m%d_%H%M%S.html",// filenamekeywords::rotation_size=max_file_size,// maximum file sizekeywords::time_based_rotation=sinks::file::rotation_at_time_point(0,0,0)// rotate every day);backend->set_file_collector(sinks::file::make_collector(keywords::target=dir,keywords::max_files=max_file_count));backend->scan_for_files(sinks::file::scan_all);// Setup log format (HTML in this case), and messages format// You could add your own stylesheet here for extended decorationbackend->auto_flush(true);backend->set_open_handler(boost::lambda::_1<<"<html><h1>Log</h1><ul>\n");backend->set_close_handler(boost::lambda::_1<<"</ul></html>\n");sink=boost::make_shared<file_sink_t>(backend);sink->set_formatter(formatter);logging::core::get()->add_sink(sink);

En el set_open_handler y set_close_handler es posible instalar los texto a añadir al log al principio de cada fichero y al final. En el ejemplo de arriba se usa un formato HTML, pero bien se podría describir cualquier otro formato.

Yalog

Este artículo se ha nutrido de la biblioteca de log yalog, la cual podéis ojear para encontrar más detalles de implementación y usar en vuestros proyectos (está publicada bajo licencia MIT).

Otras soluciones

El objetivo de esta entrada era mostrar cómo hacer un sistema de logging usando Boost. Existen otras soluciones muy buenas disponibles. Por ejemplo, una de las que más me gusta es spdlog, por su simplicidad y eficiencia. Como nota, usa cadenas de formato tipo fmt en lugar de flujos de datos (<<).

Pueden encontrarse más en este listado de GitHub.

Más opciones que se pueden implementar

Este artículo no pretende cubrir al completo Boost.Log, sino ofrecer un primer acercamiento al mismo (aunque bastante completo). Como ideas futuras que se pueden agregar están:

  • Clasificación de los mensajes en módulos o espacios de nombre, de forma que se puedan habilitar bajo demanda.
  • Soporte para múltiples formatos de ficheros (XML, HTML, logs del sistema, etc.)

Blog Bitix: Por qué proteger tu privacidad y qué información tuya se puede encontrar con una búsqueda en internet

$
0
0

La privacidad de las personas es un derecho. Un derecho que con internet y el tratamiento de datos que hacen ya todos los negocios y servicios no es fácil proteger. O aceptas los términos y condiciones de los servicios en los que quieres crear una cuenta o no permiten crearla, algunos servicios permiten cambiar algunas opciones para no recibir comunicaciones comerciales por correo electrónico pero el tratamiento de datos está implícito en la aceptación de las condiciones.

Un buscador como Google permite encontrar datos de una persona relacionada con ella incluso pasado algún lustro. A través de las redes sociales es posible conocer cualquier cosa que una persona comparta de forma pública.

Por qué proteger tu privacidad

Internet ofrece muchas posibilidades pero también tiene otros inconvenientes. Uno de ellos es que es muy fácil perder el control de la privacidad. Una vez algo se ha publicado a través de internet es difícil revocar la información y ejercer el derecho al olvido para que esa información que se desea eliminar lo sea. Una vez publicado algo en internet cualquier persona que tenga acceso lo puede copiar o republicar en cualquier otra ubicación en la que ya no se tiene el control. Lo que en un momento se considera como poco importante publicar más adelante puede desearse que no hubiese sido publicado, el problema es que publicar algo es muy fácil pero eliminar algo publicado es muy difícil.

Las redes sociales como Facebook, Instagram o Twitter permiten relacionarse con personas en cualquier parte del mundo, conocidas y desconocidas. En estas redes sociales se publica gran cantidad de información personal que alguien interesado en conocerla le permite un acceso sencillo. Con algo tan simple como publicar el nombre y apellidos de una persona ya es posible encontrar mucha otra información utilizando un buscador como Google, cualquier página pública a la que Google tenga acceso la indexa en su buscador, y a partir de aquí a más información en las redes sociales que esté como pública.

En los términos y condiciones que nadie lee al crear una cuenta en un servicio se detallan las autorizaciones que se otorga a la empresa por el hecho de usar su servicio, en esos términos con una jerga legal dificil de entender y larga para agotar en su lectura se incluyen apartados que suele detallar que el propietario del servicio procesa y compartirá los datos con terceras partes. A partir de compartir estos datos luego uno no sabe porque le llegan llamadas comerciales telefónicas cuando no se ha tenido relación ninguna con esa empresa de la que nos llama el comercial o mensajes SMS al teléfono móvil.

Algunos ataques informáticos son realizados de forma masiva pero otros son llevados a cabo de forma individualizada más laboriosa pero menos , que alguien que está intentando perpetrar un ataque informático sepa cosas de la víctima le da mayor conocimiento para realizar un ataque de ingeniería social.

Busca información tuya a través de datos que te identifican

Es fácil averiguar cuánta información personal de uno mismo hay publicada en internet con una simple búsqueda en Google cualquier dato personal que identifique a una persona. A partir de uno de estos datos personales es posible encontrar mucha información de lo que hace una persona, que piensa a través de lo que dice, fotos suyas, de sus familiares y amigos, su ciudad y lugar de residencia, de vacaciones, lugar de trabajo y profesión, aficiones, …

Los datos personales a través de los que averiguar la información que haya en internet de una persona son: nombre y un apellido, nombre y dos apellidos, DNI, número de teléfono móvil, dirección de correo electrónico o si utiliza su seudónimo. Si se sabe algo de esa persona como su ciudad de residencia permite descartar coincidencias en caso de obtener varias.

Pon en Google tu nombre y apellidos, DNI, tu correo electrónico, tu número de móvil que son algunas cosas que te identifican y mira la información que encuentras de ti mismo. Cuando se dice que Google conoce más de ti que tú mismo es cierto en el aspecto de que muy posiblemente hay cosas que tu ya has olvidado pero Google es capaz de encontrar.

Y Google también es capaz de reconocer texto en las imágenes. Busca también en Google Imágenes ahí también se encuentran fotos a partir de los datos identificativos.

Conclusión

Quizá te asustes de lo que puede conocer alguien de ti con interés por información que tú mismo has publicado. En el momento de publicar la información quizá no se le da importancia pero en el futuro en alguna circunstancia quizá se desease eliminar esa información cosa que erá muy difícil o quizá no sea posible.

Cada uno es libre de hacer con su privacidad lo que mejor le parezca. Yo recomiendo protegerla porque es fácil perderla pero muy difícil recuperarla. La privacidad no involucra solo la de uno mismo sino también la de los demás, si tú no le das importancia a tu privacidad otras personas si se la damos por ello si publicas datos o fotos no publiques ninguna que incluya a ninguna persona de la que no tengas su consentimiento.

La razón de utilizar un pseudónimo en internet es para utilizar un nombre que no sea el nombre y apellidos reales, esto permite separar en parte el alter ego de la persona real y desecharlo en caso de desearlo.

Yo suelo decir…

A mi me encanta LinkedIn, y eso que no tengo cuenta.

-  picodotdev

Variable not found: Enlaces interesantes 461

$
0
0
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Blog Bitix: Ejemplo de un potencial ataque de phishing, El caso de El Gatico Biever

$
0
0

A estas alturas la mayoría de la gente seguramente ya haya recibido a través de un medio u otro algún intento de tipo de ataque informático, ya sea a través del correo electrónico, mensajes SMS con enlaces o a través de aplicaciones de mensajería instantánea. Los ataques informáticos cada vez van a ir a más y serán más peligrosos a medida que más operaciones se realicen a través de internet, surgirán medidas adicionales de seguridad para evitarlos como el segundo factor de autenticación pero también surgirán nuevas formas de ataque, donde el componente humano seguramente siga siendo la parte más débil del sistema de seguridad. Este artículo es el relato de la historia de un potencial ataque informático de phishing.

Los ataques informáticos ya no se producen solo por descargar de una una fuente no confiable y ejecutar un programa en el ordenador, ni siquiera estos son los más peligrosos. Un virus informático requiere conocimientos avanzados de programación, tiempo para desarrollar un programa con la función maliciosa que no sea bloqueada por las medidas de seguridad del sistema operativo y distribuirla de alguna forma entre las potenciales víctimas para que se lo descarguen, los virus informáticos son una forma muy elaborada de realizar un ataque informático.

Aparte de los virus hay otras formas de ataque informático mucho más sencillas de desarrollar y de distribuir. Una ataque de phishing simplemente requiere desarrollar una página en la que la víctima introduzca los datos que se deseen robar que van desde información personal hasta credenciales de inicio de sesión en la banca online, servicios como Gmail o PayPal o los datos de la tarjeta de crédito con los que robar el límite de saldo diariamente que la tarjeta permita hasta que el usuario o el banco la bloqueen.

Una vez está desarrollada la página de phising el siguiente paso es hacer que las víctimas accedan a ella, tan simple como enviar un enlace por algún medio como un mensaje de correo electrónico, mensaje SMS o una aplicación de mensajería instantánea a través del móvil.

Contenido del artículo

El caso de El Gatico Biever

En este artículo comento un potencial caso como ejemplo y una vez leído me puedes comentar si crees que este era un ataque informático. En el que denominaré El caso del Gatico Biever está basado en una conversación real que mantuve por correo electrónico a la que he cambiado el nombre real del contacto y comentado los hechos relevantes del contenido de los mensajes.

Sin más, os dejo con la narración de El caso del Gatico Biever.

El contacto

Tengo un blog con ya casi una década de vida y más de 600 artículos publicados algunos posicionados en las primeras posiciones de las páginas de resultados por algunas combinaciones de palabras clave. El blog tiene casi 2.5K páginas vistas diariamente y unas 65K páginas mensuales.

Por algún motivo que desconozco pero supongo por el buen posicionamiento de algunas páginas y la autoridad del dominio, me sorprende la buena cantidad de comerciales que me contactan solicitando publicar algún artículo a cambio de una pequeña compensación económica. Quizá no todas las semanas recibo una oferta para publicar un artículo pero si cada uno o dos meses, algunas llegan a buen fin otras simplemente se quedan en el conocimiento de las condiciones.

El interés de estos comerciales al publicar el artículo es incluir algún enlace en los artículos hacia alguna página o servicio por motivos de SEO, a veces el interés es simplemente insertar un enlace en un artículo ya posicionado. Dar a conocer una página web o servicio desde cero o hacerlo crecer es difícil y requiere tiempo, para reducir este tiempo están dispuestos a pagar a sitios web existentes.

Uno de estos meses recibí un correo electrónico como remitente el Gatico Biever utilizando una dirección de Gmail precisamente proponiendome una oferta de colaboración para el blog con la intención de publicar hasta seis artículos al mes durante varios meses. Una oferta extraordinaria fuera de lo normal que suele ser exclusivamente de un artículo. El correo electrónico estaba redactado en inglés pero haciendo referencia al dominio de mi blog en el asunto del mensaje y diciendo que era un lector asiduo de mi blog.

El primer paso en estos contactos comerciales suele ser la negociación de las condiciones.

La negociación y la propuesta

Una oferta de seis artículos al mes y durante varios meses parece una oferta muy atractiva. Los primeros puntos a conocer es en qué consiste el acuerdo si en la inserción de enlaces, publicar un artículo ya redactado o que escriba yo un artículo original en función de lo cual se determina el precio ya que cada una me requiere menos o más tiempo.

Una vez conocida en qué consiste la colaboración está en la aceptación de las condiciones como que la temática de los artículos esté relacionado la programación, tecnología o software libre así como vetar algunas temáticas de artículos como apuestas, juegos de azar y otras temáticas controvertidas. Otras condiciones es que en el caso de los artículos deben ser únicos para evitar penalizaciones por contenido de publicar y ser detectado como un sitio de contenido no deseado. Comprar artículos y enlaces es una actividad que en caso de que Google la detecte la penaliza ya que es una forma de alternar y algoritmo de posicionamiento de una forma no permitida por Google.

Seis artículos patrocinados al mes son muchos artículos, casi más de los que escribo como contenido del blog. Para limitar el contenido patrocinado le propongo que solo acepto uno o dos artículos al mes.

Otro asunto importante de la colaboración es llegar a un acuerdo en el tema económico, poner un precio por publicar el artículo. Yo suelo ser claro y aunque puedo dejar ver que oferta me hacen suelo ir directo al tema para acabar negociar este punto sin mucha demora. Casi siempre empiezo con mi propuesta de oferta económica.

Hecha mi primera oferta económica al Gatito Biever este me responde con que esta le parece demasiado alta diciendo que su artículos son de calidad y la colaboración serán varios, no me indica en qué precio a él le parece bien el acuerdo económico sino que me deja en una pregunta abierta a que le haga otra oferta. Le hago una segunda oferta económica, que también rechaza y me propone su oferta económica que si fuera por un único artículo probablemente no aceptaría.

Como la colaboración iba a ser de varios artículos acepto su oferta con la condición de que los dos primeros fueran a un precio intermedio entre lo que ambos proponíamos, en los siguientes artículos al precio de lo que él proponía.

Las sospechas

Acordados los términos de la colaboración y el precio comienza la colaboración que en este caso es simplemente que el Gatico Biever me proporcione el contenido del artículo, yo lo publique lo cual no suelo tardar más de uno o dos días y procedamos al pago en los términos acordados.

Pasa casi una semana sin que sepa nada del Gatico Biever con lo que me pongo en contacto con él para ver qué hay del asunto. Me responde al cabo de unos días diciendo que está trabajando en ello y me pide que elimine la página el publicidad en la que detallo que mi blog ofrece la posibilidad de este tipo de colaboraciones, en el correo me incluye la dirección de la página que quiere que elimine con el texto el de la dirección de la página pero el enlace tiene una dirección de un dominio que desconozco, le hago un curl a esa URL y parece simplemente una redirección a la página de mi blog pero a través de un dominio extraño.

El motivo para solicitar la eliminación de esta página es para evitar penalizaciones por SEO ya que este tipo de colaboraciones no es algo aceptado por Google y seguramente lo penalice en casos extremos. La página de publicidad la tengo desde hace mucho tiempo y no he notado estar penalizado por Google.

Aquí es donde empiezo a sospechar ya que en sus correos utiliza el típico lenguaje de acción rápida como hazlo lo más pronto posible, respondeme hoy cuando él tarda en contestar varios días. Le insisto en que esa página de publicidad no es ningún problema y que me proporcione el contenido del artículo ya poniéndome un poco borde saludándose con un Hola Gatico y para finalizar su misma urgencia con un ASAP.

Él tarda nuevamente en responder un par de días. Me pongo de nuevo en contacto con él siendo nuevamente borde con que su actitud no es nada profesional. Si alguien me contesta en los mismos términos en los que yo lo hago inmediatamente termino con la colaboración, pero él no, no cae en la provocación me dice que él es un experto en SEO y que eliminar esa página es un requisito indispensable para su cliente.

Me doy cuenta que en realidad se poco de el Gatico Biever, me escribe en inglés y el dominio oculto del enlace de redirección parece de UK. Le pregunto que si es de UK y que tal van las cosas por UK con la situación que tienen del Brexit con un tono burlesco porque en un primer momento pienso que es alguien gastando una broma. Nuevamente si alguien se dirige a mi en los mismos términos que yo lo hago yo terminaría la colaboración. Pero él no, él responde con un «Sí, sí, lo has entendido bien» a lo de que él es de UK y que hablaremos más adelante cuando tenga un poco más de tiempo.

Otro correo me responde con un «Seguro querido», un ¿querido?, me dice que nos centremos en los negocios y que su cliente «Indulgente» está esperando a que elimine la página de publicidad.

Me doy cuenta de que en realidad se poco de el Gatico Biever, su «sí, sí» parece irónico y condescendiente y el «indulgente» parece muy… no se como definirlo ¿sacro? ¿de practicante, creyente, fiel religioso?, hacer colaboraciones profesionales con una cuenta que como nombre tiene Gatico Biever con una foto de catálogo que se encuentra y he encontrado fácilmente en una búsqueda por imágenes no parece profesional.

Llega la trampa, mi pequeña trampa.

La trampa

No estoy dispuesto a eliminar esa página de publicidad y ya estoy sospechando de que este sea un ataque informático aunque aún no se qué forma tendrá el ataque.

Me doy cuenta de que en realidad se poco del Gatico Biever, no es una cuenta profesional ni pone de que empresa de consultoría SEO pertenece, simplemente se identifica con un equipo SEO como organización en la despedida del mensaje.

Preparo un enlace a una página que tiene un enlace similar a la página de publicidad pero algo modificada que si uno no se fija en detalle pasa desapercibido que las páginas son diferentes. Si la página de publicidad es /publicidad le preparo una página /publiciidad que simula un error de página no encontrada como desea el Gatico Biever que haga.

Le envío en un nuevo correo electrónico el enlace de la página de publicidad trucado esperando que él haga clic en él. Esta es la misma técnica para realizar un ataque de phishing en vez de utilizando otro dominio añadiendo simplemente un caracter de una nueva URL parecida a la original, como el dominio y sus URLs lo controlo yo puedo hacerlo y lo hago.

¿Caerá en la trampa? Necesita hacer clic en el enlace que le he enviado yo, si entra directamente a la página para comprobar si he eliminado la página de publicidad no es de mucha utilidad.

Pues Gatico Biever cae en la trampa hace clic en enlace directamente desde el correo electrónico y como se que ese enlace solo lo tiene él sé que ha sido él, ahora analizo los datos que me proporciona Google Analytics para conocer algo más de el Gatico Biever.

La exploración

Los datos de Analytics me permiten ver unos datos básicos anónimos pero algo más de quien es el Gatico Biever como su país de origen, que navegador utiliza y que sistema operativo utiliza. Veo que su país de origen es Pakistan, su sistema operativo es Windows 10 y el navegador web que utiliza es Google Chrome actualizado a la última versión.

El país de origen me pone en alerta ya que es un país de oriente medio en una zona posiblemente en conflictos armados. Seguramente no tenga muchos visitantes de Pakistan asi que creo un segmento con los visitantes de este país y miro qué páginas ha visitado. No ha visitado muchas páginas pero veo que se ha parado alguna algo más de tiempo en la que hablaba de PayPal, la hemeroteca donde también hablaba de dinero y otra donde mencionaba la aplicación autenticador de Google. Otro dato que veo es que además de visitar la página preparada por mi ha visitado la página de publicidad original después de proporcionarle el enlace, asi que sé que sabe que en realidad no he eliminado la página de publicidad.

El primer correo ya me debería haber hecho sospechar, por el mismo nombre del remitente, parecer una plantilla, decir que me visita regularmente alguien que habla en inglés. Ahora con estos datos tengo aún más sospechas. Aún no sé de qué forma será el ataque ni qué interés tiene esta yinkana de eliminar la página de publicidad en todo ello, igual es un filtro para discriminar a usuarios fáciles de los difíciles o de adoctrinar a la víctima para que haga lo que se le dice.

El Gatico Biever ignora que en realidad no he eliminado la página de publicidad y me envía el contenido del artículo. Analizó el contenido del artículo que está en buen español, no parece un artículo que esté obteniendo de internet ni esté ya publicado en otro sitio web. Me dice que lo publique cuanto antes porque tiene varios artículos más.

Le digo que mientras lo publico me conteste de qué forma me va a pagar con una pregunta abierta. Me contesta que me paga con PayPal pero no cuál será el procedimiento, así que le insisto con cual es el procedimiento que suele utilizar para hacer el pago. Me responde con un «querido» y me dice con un tono imperativo en lo que yo haré que su procedimiento es que yo le proporcione mi dirección de PayPal en la que hacerme el pago y que me envía un enlace para que compruebe que me ha hecho el pago.

Vale ahora tengo claro cual es su forma de ataque si es que es un ataque, un ataque de phishing sobre la página de PayPal. Pobre Gatico Biever que si este es su ataque no sabe que tengo activado el segundo factor de autenticación, no es infalible pero si no lo impide al menos limita el tiempo en el que es posible el ataque, concretamente tienen unos 30 segundos en caso de que sea víctima si su ataque de phishing soporta el segundo factor de autenticación que no creo.

Le pido más información con la excusa de que por razones legales le tengo que emitir una factura para pagar impuestos, con lo que le pido cierta información como nombre y apellidos, dirección y nombre de la compañía.

Parece que se ha cansado de esta pequeña yinkana que le estoy haciendo y me propone sin yo haber publicado el artículo todavía hacerme el pago por adelantado con lo que me pide mi dirección de correo asociada a PayPal y nuevamente me repite que me proporcionará un enlace que podré usar para comprobar el pago.

Aquí ya tengo la intención de dejarlo pasar, podría ir más lejos para que me envíe el enlace de la página de phishing, podría inventarme cualquier dirección de correo electrónico como por ejemplo felipin.demaritxalar.yvorvon[at]gmail.com a ver si es capaz de hacer el pago y enviarme el enlace para que lo compruebe que sospecho es de phishing. ¿O será ese nombre demasiado evidente que se de cuenta? Posiblemente para alguien de Pakistan no sea tan evidente. Si le doy una dirección de PayPal, supongo que me insistirá en que me ha hecho el pago y que lo compruebe.

Como ve que ya no respondo me envía un nuevo correo al cabo de una semana con unos datos para atender a mi petición. Me dice que es de Reino Unido y me da como nombre real Ethan Biever. Busco por el nombre que me da y las primeras referencias son los nombres de dos personajes de un película.

Llegar hasta el punto de que me de el enlace de phishing tampoco tiene ninguna utilidad, no soy policía, muy posiblemente ni ellos podrían hacer algo aunque fuese víctima del ataque y aunque le denuncie ante Google es seguro que será capaz de crearse una nueva dirección de correo electrónico con la que seguir haciendo ataques.

El final, ¿tú que crees?

Bueno, la mayoría sois lectores, otras personas equivalentes a mi serán youtubers, podcasters o streamers pero todavía quedamos algunos bloggers de la vieja escuela, en cualquier caso este es solo un ejemplo, podría llegar en realidad a cualquiera persona ni siquiera estar englobada en ningún colectivo y podría ser de otra forma con alguna excusa que un delincuente tenga su correo electrónico y una forma de contactarte por el ordenador o con teléfono inteligente.

Los indicios que parecen indicar ser un ataque informático son el nombre de la cuenta, la forma de dirigirse a mí con un «querido», una oferta de colaboración muy atractiva respecto de lo que suele ser lo habitualmente, algunas respuestas que me da condescendientes, ignora mi mala educación y falta de respeto, ignora que no he hecho lo que me ha pedido de eliminar la página de publicidad, su país de origen, utilizar lenguaje imperativo, pedir inmediatez y se ofrece a hacerme el pago por adelantado sin yo haber publicado el artículo.

El perfil de la persona que me hago del tipo de Gatico Biever es el siguiente. Aceptan tus insultos y faltas de respeto mientras te están esperando a que cometas un error, tus insultos los soportan hasta que cometes el error, disfrutan de tu desorientación como cuando le pregunto si es de UK y me responde con un «si, si». Es como si buscarán duelos o peleas, pero no son duelos cara a cara son duelos de engaño, en los que dan la imagen de ir todo bien, pierde es el que cae en la trampa. Se burlan a su modo, de forma velada con lo de «Indulgente», igual que yo con lo de «froilin» o su propio nombre sacado de una película.

No se que criterio ha elegido para realizar un ataque, no sé si entenderá algo de español y habrá investigado algo sobre la víctima en este caso yo con lo que he publicado en en blog y mi cuenta de Twitter, posiblemente haya recopilado un conjunto de direcciones de correo electrónico públicas y enviado un mensaje a ver cuantos responden. Porque elegir como víctima de un ataque informático a un usuario que es informático y que usa GNU/Linux no parece la víctima ideal, es como intentar ir a robar la casa de un cerrajero. Qué lo puede intentar pero ambos sabemos mucho más de las técnicas que utilizan los delincuentes para cometer sus delitos y seguramente las medidas de seguridad que tenemos son mucho mejores. El cerrajero utilizando una puerta acorazada, una cerradura que evite las técnicas conocidas de apertura sin forzado, técnicas para detectar si una casa está habitada o un escudo en la cerradura que evite ciertas técnicas de forzado. Yo por mi parte como informático es posible que conozco y conozco el segundo factor de autenticación y tengo las nociones básicas de ataques informáticos.

Parece un ataque de phishing¿tu que crees? Porque claro no voy a seguir hasta el final para comprobarlo. Al menos le he hecho perder un poco de tiempo, he marcado sus correos como no deseados o spam y le he denunciado en Gmail como ataque de phishing que no sé si servirá de algo o será suficiente para que Google tome alguna acción.

Fin.

Cómo denunciar el intento o ataque informático

Cómo comentaba en el artículo nociones básicas para detectar un ataque y evitarlo en caso de ser víctima de un ataque conviene denunciarlo. La unidad de delitos informáticos de los diferentes cuerpos de policía y un perito judicial informático seguro que os podría contar cientos de casos, pero seguramente el mejor consejo que den sea evitar ser víctima de un ataque informático. Ellos están para ayudar, proteger, minimizar daños, prevenir nuevos delitos, obtener pruebas y poner a disposición de la justicia a delincuentes pero muchas veces tras haber ocurrido los hechos el grave daño causado ya no es reparable. Y a veces les será muy difícil por estar los delincuentes en otros países. Muchos ataques informáticos como este ejemplo no son difíciles de detectar con las nociones básicas.

En los términos y condiciones del correo electrónico de Gmail no permite utilizarlo para realizar actividades ilegales incluyendo el phishing y ofrecen herramientas para denunciarlo, desde el propio Gmail y desde páginas específicas. Para denunciar una cuenta de correo que esté siendo utilizada para realizar actividades ilegales es posible tomar dos medidas, una marcar el correo como spam que Gmail tiene en cuenta, si son varios usuarios lo que lo hacen los correos del remitente a los usuarios les llegará a la carpeta de spam en vez de a la bandeja de entrada. La segunda opción es denunciar un mensaje como suplantación de identidad, aunque en realidad el Gatico Biever no me ha enviado el enlace de phishing.

En caso de recibir el enlace es posible además denunciar la página de phishing para que esta sea incluida en la lista negra de páginas identificadas maliciosas. Supongo una persona que trabaje para Google analizará estas peticiones y en caso de corroborarlo la página será añadida a la lista negra. Esta lista negra es utilizada por los navegadores para mostrar un mensaje de advertencia cuando un usuario intente entrar en ella, poniendo sobre aviso al usuario y aconsejando no entrar.

Minimizar daños de posibles ataques informáticos

Nadie está exento de ataques, ni alguien como yo que tiene conocimientos en informática y conozco las nociones básicas de los ataques, que inicialmente me resultó extraño el correo pero que hasta bastante avanzada la conversación con unos cuantos correos electrónicos enviados no empecé a realmente sospechar.

Por ello conviene tomar una serie de medidas como establecer límites transferencias y tarjeta de crédito más bajos que los que establecen por defecto los bancos que suelen ser muy generosos, activar el segundo factor de autenticación para que aunque roben las credenciales de una cuenta evitar el ataque o permitirlo únicamente durante un breve periodo de tiempo si la página de phishing fuera tan avanzada como para estar preparada para obtener también el segundo factor de autenticación.

No hay otra opción de que quede impune, si es un delincuente y parece serlo por los varios indicios va a continuar haciendo su actividad y algún usuario más incauto sea su víctima, está claro que si realizan esta actividad es porque obtienen algún beneficio. La conclusión en cualquier caso es, se bueno pero ten un poco de joputismo para conocer a los malos, hay una buena cantidad de joputas malos por ahí.


Blog Bitix: Ejemplo de un potencial ataque informático de phishing, El caso de El Gatico Biever

$
0
0

A estas alturas la mayoría de la gente seguramente ya haya recibido a través de un medio u otro algún intento de tipo de ataque informático, ya sea a través del correo electrónico, mensajes SMS con enlaces o a través de aplicaciones de mensajería instantánea. Los ataques informáticos cada vez van a ir a más y serán más peligrosos a medida que más operaciones se realicen a través de internet, surgirán medidas adicionales de seguridad para evitarlos como el segundo factor de autenticación pero también surgirán nuevas formas de ataque, donde el componente humano seguramente siga siendo la parte más débil del sistema de seguridad. Este artículo es el relato de la historia de un potencial ataque informático de phishing.

Los ataques informáticos ya no se producen solo por descargar de una una fuente no confiable y ejecutar un programa en el ordenador, ni siquiera estos son los más peligrosos. Un virus informático requiere conocimientos avanzados de programación, tiempo para desarrollar un programa con la función maliciosa que no sea bloqueada por las medidas de seguridad del sistema operativo y distribuirla de alguna forma entre las potenciales víctimas para que se lo descarguen, los virus informáticos son una forma muy elaborada de realizar un ataque informático.

Aparte de los virus hay otras formas de ataque informático mucho más sencillas de desarrollar y de distribuir. Una ataque de phishing simplemente requiere desarrollar una página en la que la víctima introduzca los datos que se deseen robar que van desde información personal hasta credenciales de inicio de sesión en la banca online, servicios como Gmail o PayPal o los datos de la tarjeta de crédito con los que robar el límite de saldo diariamente que la tarjeta permita hasta que el usuario o el banco la bloqueen.

Una vez está desarrollada la página de phising el siguiente paso es hacer que las víctimas accedan a ella, tan simple como enviar un enlace por algún medio como un mensaje de correo electrónico, mensaje SMS o una aplicación de mensajería instantánea a través del móvil.

Contenido del artículo

El caso de El Gatico Biever

En este artículo comento un potencial caso como ejemplo y una vez leído me puedes comentar si crees que este era un ataque informático. En el que denominaré El caso del Gatico Biever está basado en una conversación real que mantuve por correo electrónico a la que he cambiado el nombre real del contacto y comentado los hechos relevantes del contenido de los mensajes.

Sin más, os dejo con la narración de El caso del Gatico Biever.

El contacto

Tengo un blog con ya casi una década de vida y más de 600 artículos publicados algunos posicionados en las primeras posiciones de las páginas de resultados por algunas combinaciones de palabras clave. El blog tiene casi 2.5K páginas vistas diariamente y unas 65K páginas mensuales.

Por algún motivo que desconozco pero supongo por el buen posicionamiento de algunas páginas y la autoridad del dominio, me sorprende la buena cantidad de comerciales que me contactan solicitando publicar algún artículo a cambio de una pequeña compensación económica. Quizá no todas las semanas recibo una oferta para publicar un artículo pero si cada uno o dos meses, algunas llegan a buen fin otras simplemente se quedan en el conocimiento de las condiciones.

El interés de estos comerciales al publicar el artículo es incluir algún enlace en los artículos hacia alguna página o servicio por motivos de SEO, a veces el interés es simplemente insertar un enlace en un artículo ya posicionado. Dar a conocer una página web o servicio desde cero o hacerlo crecer es difícil y requiere tiempo, para reducir este tiempo están dispuestos a pagar a sitios web existentes.

Uno de estos meses recibí un correo electrónico como remitente el Gatico Biever utilizando una dirección de Gmail precisamente proponiendome una oferta de colaboración para el blog con la intención de publicar hasta seis artículos al mes durante varios meses. Una oferta extraordinaria fuera de lo normal que suele ser exclusivamente de un artículo. El correo electrónico estaba redactado en inglés pero haciendo referencia al dominio de mi blog en el asunto del mensaje y diciendo que era un lector asiduo de mi blog.

El primer paso en estos contactos comerciales suele ser la negociación de las condiciones.

La negociación y la propuesta

Una oferta de seis artículos al mes y durante varios meses parece una oferta muy atractiva. Los primeros puntos a conocer es en qué consiste el acuerdo si en la inserción de enlaces, publicar un artículo ya redactado o que escriba yo un artículo original en función de lo cual se determina el precio ya que cada una me requiere menos o más tiempo.

Una vez conocida en qué consiste la colaboración está en la aceptación de las condiciones como que la temática de los artículos esté relacionado la programación, tecnología o software libre así como vetar algunas temáticas de artículos como apuestas, juegos de azar y otras temáticas controvertidas. Otras condiciones es que en el caso de los artículos deben ser únicos para evitar penalizaciones por contenido de publicar y ser detectado como un sitio de contenido no deseado. Comprar artículos y enlaces es una actividad que en caso de que Google la detecte la penaliza ya que es una forma de alternar y algoritmo de posicionamiento de una forma no permitida por Google.

Seis artículos patrocinados al mes son muchos artículos, casi más de los que escribo como contenido del blog. Para limitar el contenido patrocinado le propongo que solo acepto uno o dos artículos al mes.

Otro asunto importante de la colaboración es llegar a un acuerdo en el tema económico, poner un precio por publicar el artículo. Yo suelo ser claro y aunque puedo dejar ver que oferta me hacen suelo ir directo al tema para acabar negociar este punto sin mucha demora. Casi siempre empiezo con mi propuesta de oferta económica.

Hecha mi primera oferta económica al Gatito Biever este me responde con que esta le parece demasiado alta diciendo que su artículos son de calidad y la colaboración serán varios, no me indica en qué precio a él le parece bien el acuerdo económico sino que me deja en una pregunta abierta a que le haga otra oferta. Le hago una segunda oferta económica, que también rechaza y me propone su oferta económica que si fuera por un único artículo probablemente no aceptaría.

Como la colaboración iba a ser de varios artículos acepto su oferta con la condición de que los dos primeros fueran a un precio intermedio entre lo que ambos proponíamos, en los siguientes artículos al precio de lo que él proponía.

Las sospechas

Acordados los términos de la colaboración y el precio comienza la colaboración que en este caso es simplemente que el Gatico Biever me proporcione el contenido del artículo, yo lo publique lo cual no suelo tardar más de uno o dos días y procedamos al pago en los términos acordados.

Pasa casi una semana sin que sepa nada del Gatico Biever con lo que me pongo en contacto con él para ver qué hay del asunto. Me responde al cabo de unos días diciendo que está trabajando en ello y me pide que elimine la página el publicidad en la que detallo que mi blog ofrece la posibilidad de este tipo de colaboraciones, en el correo me incluye la dirección de la página que quiere que elimine con el texto el de la dirección de la página pero el enlace tiene una dirección de un dominio que desconozco, le hago un curl a esa URL y parece simplemente una redirección a la página de mi blog pero a través de un dominio extraño.

El motivo para solicitar la eliminación de esta página es para evitar penalizaciones por SEO ya que este tipo de colaboraciones no es algo aceptado por Google y seguramente lo penalice en casos extremos. La página de publicidad la tengo desde hace mucho tiempo y no he notado estar penalizado por Google.

Aquí es donde empiezo a sospechar ya que en sus correos utiliza el típico lenguaje de acción rápida como hazlo lo más pronto posible, respondeme hoy cuando él tarda en contestar varios días. Le insisto en que esa página de publicidad no es ningún problema y que me proporcione el contenido del artículo ya poniéndome un poco borde saludándose con un Hola Gatico y para finalizar su misma urgencia con un ASAP.

Él tarda nuevamente en responder un par de días. Me pongo de nuevo en contacto con él siendo nuevamente borde con que su actitud no es nada profesional. Si alguien me contesta en los mismos términos en los que yo lo hago inmediatamente termino con la colaboración, pero él no, no cae en la provocación me dice que él es un experto en SEO y que eliminar esa página es un requisito indispensable para su cliente.

Me doy cuenta que en realidad se poco de el Gatico Biever, me escribe en inglés y el dominio oculto del enlace de redirección parece de UK. Le pregunto que si es de UK y que tal van las cosas por UK con la situación que tienen del Brexit con un tono burlesco porque en un primer momento pienso que es alguien gastando una broma. Nuevamente si alguien se dirige a mi en los mismos términos que yo lo hago yo terminaría la colaboración. Pero él no, él responde con un «Sí, sí, lo has entendido bien» a lo de que él es de UK y que hablaremos más adelante cuando tenga un poco más de tiempo.

Otro correo me responde con un «Seguro querido», un ¿querido?, me dice que nos centremos en los negocios y que su cliente «Indulgente» está esperando a que elimine la página de publicidad.

Me doy cuenta de que en realidad se poco de el Gatico Biever, su «sí, sí» parece irónico y condescendiente y el «indulgente» parece muy… no se como definirlo ¿sacro? ¿de practicante, creyente, fiel religioso?, hacer colaboraciones profesionales con una cuenta que como nombre tiene Gatico Biever con una foto de catálogo que se encuentra y he encontrado fácilmente en una búsqueda por imágenes no parece profesional.

Llega la trampa, mi pequeña trampa.

La trampa

No estoy dispuesto a eliminar esa página de publicidad y ya estoy sospechando de que este sea un ataque informático aunque aún no se qué forma tendrá el ataque.

Me doy cuenta de que en realidad se poco del Gatico Biever, no es una cuenta profesional ni pone de que empresa de consultoría SEO pertenece, simplemente se identifica con un equipo SEO como organización en la despedida del mensaje.

Preparo un enlace a una página que tiene un enlace similar a la página de publicidad pero algo modificada que si uno no se fija en detalle pasa desapercibido que las páginas son diferentes. Si la página de publicidad es /publicidad le preparo una página /publiciidad que simula un error de página no encontrada como desea el Gatico Biever que haga.

Le envío en un nuevo correo electrónico el enlace de la página de publicidad trucado esperando que él haga clic en él. Esta es la misma técnica para realizar un ataque de phishing en vez de utilizando otro dominio añadiendo simplemente un caracter de una nueva URL parecida a la original, como el dominio y sus URLs lo controlo yo puedo hacerlo y lo hago.

¿Caerá en la trampa? Necesita hacer clic en el enlace que le he enviado yo, si entra directamente a la página para comprobar si he eliminado la página de publicidad no es de mucha utilidad.

Pues Gatico Biever cae en la trampa hace clic en enlace directamente desde el correo electrónico y como se que ese enlace solo lo tiene él sé que ha sido él, ahora analizo los datos que me proporciona Google Analytics para conocer algo más de el Gatico Biever.

La exploración

Los datos de Analytics me permiten ver unos datos básicos anónimos pero algo más de quien es el Gatico Biever como su país de origen, que navegador utiliza y que sistema operativo utiliza. Veo que su país de origen es Pakistan, su sistema operativo es Windows 10 y el navegador web que utiliza es Google Chrome actualizado a la última versión.

El país de origen me pone en alerta ya que es un país de oriente medio en una zona posiblemente en conflictos armados. Seguramente no tenga muchos visitantes de Pakistan asi que creo un segmento con los visitantes de este país y miro qué páginas ha visitado. No ha visitado muchas páginas pero veo que se ha parado alguna algo más de tiempo en la que hablaba de PayPal, la hemeroteca donde también hablaba de dinero y otra donde mencionaba la aplicación autenticador de Google. Otro dato que veo es que además de visitar la página preparada por mi ha visitado la página de publicidad original después de proporcionarle el enlace, asi que sé que sabe que en realidad no he eliminado la página de publicidad.

El primer correo ya me debería haber hecho sospechar, por el mismo nombre del remitente, parecer una plantilla, decir que me visita regularmente alguien que habla en inglés. Ahora con estos datos tengo aún más sospechas. Aún no sé de qué forma será el ataque ni qué interés tiene esta yincana de eliminar la página de publicidad en todo ello, igual es un filtro para discriminar a usuarios fáciles de los difíciles o de adoctrinar a la víctima para que haga lo que se le dice.

El Gatico Biever ignora que en realidad no he eliminado la página de publicidad y me envía el contenido del artículo. Analizó el contenido del artículo que está en buen español, no parece un artículo que esté obteniendo de internet ni esté ya publicado en otro sitio web. Me dice que lo publique cuanto antes porque tiene varios artículos más.

Le digo que mientras lo publico me conteste de qué forma me va a pagar con una pregunta abierta. Me contesta que me paga con PayPal pero no cuál será el procedimiento, así que le insisto con cual es el procedimiento que suele utilizar para hacer el pago. Me responde con un «querido» y me dice con un tono imperativo en lo que yo haré que su procedimiento es que yo le proporcione mi dirección de PayPal en la que hacerme el pago y que me envía un enlace para que compruebe que me ha hecho el pago.

Vale ahora tengo claro cual es su forma de ataque si es que es un ataque, un ataque de phishing sobre la página de PayPal. Pobre Gatico Biever que si este es su ataque no sabe que tengo activado el segundo factor de autenticación, no es infalible pero si no lo impide al menos limita el tiempo en el que es posible el ataque, concretamente tienen unos 30 segundos en caso de que sea víctima si su ataque de phishing soporta el segundo factor de autenticación que no creo.

Le pido más información con la excusa de que por razones legales le tengo que emitir una factura para pagar impuestos, con lo que le pido cierta información como nombre y apellidos, dirección y nombre de la compañía.

Parece que se ha cansado de esta pequeña yincana que le estoy haciendo y me propone sin yo haber publicado el artículo todavía hacerme el pago por adelantado con lo que me pide mi dirección de correo asociada a PayPal y nuevamente me repite que me proporcionará un enlace que podré usar para comprobar el pago.

Aquí ya tengo la intención de dejarlo pasar, podría ir más lejos para que me envíe el enlace de la página de phishing, podría inventarme cualquier dirección de correo electrónico como por ejemplo felipin.demaritxalar.yvorvon[at]gmail.com a ver si es capaz de hacer el pago y enviarme el enlace para que lo compruebe que sospecho es de phishing. ¿O será ese nombre demasiado evidente que se de cuenta? Posiblemente para alguien de Pakistan no sea tan evidente. Si le doy una dirección de PayPal, supongo que me insistirá en que me ha hecho el pago y que lo compruebe.

Como ve que ya no respondo me envía un nuevo correo al cabo de una semana con unos datos para atender a mi petición. Me dice que es de Reino Unido y me da como nombre real Ethan Biever. Busco por el nombre que me da y las primeras referencias son los nombres de dos personajes de un película.

Llegar hasta el punto de que me de el enlace de phishing tampoco tiene ninguna utilidad, no soy policía, muy posiblemente ni ellos podrían hacer algo aunque fuese víctima del ataque y aunque le denuncie ante Google es seguro que será capaz de crearse una nueva dirección de correo electrónico con la que seguir haciendo ataques.

El final, ¿tú que crees?

Bueno, la mayoría sois lectores, otras personas equivalentes a mi serán youtubers, podcasters o streamers pero todavía quedamos algunos bloggers de la vieja escuela, en cualquier caso este es solo un ejemplo, podría llegar en realidad a cualquiera persona ni siquiera estar englobada en ningún colectivo y podría ser de otra forma con alguna excusa que un delincuente tenga su correo electrónico y una forma de contactarte por el ordenador o con teléfono inteligente.

Los indicios que parecen indicar ser un ataque informático son el nombre de la cuenta, la forma de dirigirse a mí con un «querido», una oferta de colaboración muy atractiva respecto de lo que suele ser lo habitualmente, algunas respuestas que me da condescendientes, ignora mi mala educación y falta de respeto, ignora que no he hecho lo que me ha pedido de eliminar la página de publicidad, su país de origen, utilizar lenguaje imperativo, pedir inmediatez y se ofrece a hacerme el pago por adelantado sin yo haber publicado el artículo.

El perfil de la persona que me hago del tipo de Gatico Biever es el siguiente. Aceptan tus insultos y faltas de respeto mientras te están esperando a que cometas un error, tus insultos los soportan hasta que cometes el error, disfrutan de tu desorientación como cuando le pregunto si es de UK y me responde con un «si, si». Es como si buscarán duelos o peleas, pero no son duelos cara a cara son duelos de engaño, en los que dan la imagen de ir todo bien, pierde es el que cae en la trampa. Se burlan a su modo, de forma velada con lo de «Indulgente», igual que yo con lo de «froilin» o su propio nombre sacado de una película.

No se que criterio ha elegido para realizar un ataque, no sé si entenderá algo de español y habrá investigado algo sobre la víctima en este caso yo con lo que he publicado en en blog y mi cuenta de Twitter, posiblemente haya recopilado un conjunto de direcciones de correo electrónico públicas y enviado un mensaje a ver cuantos responden. Porque elegir como víctima de un ataque informático a un usuario que es informático y que usa GNU/Linux no parece la víctima ideal, es como intentar ir a robar la casa de un cerrajero. Qué lo puede intentar pero ambos sabemos mucho más de las técnicas que utilizan los delincuentes para cometer sus delitos y seguramente las medidas de seguridad que tenemos son mucho mejores. El cerrajero utilizando una puerta acorazada, una cerradura que evite las técnicas conocidas de apertura sin forzado, técnicas para detectar si una casa está habitada o un escudo en la cerradura que evite ciertas técnicas de forzado. Yo por mi parte como informático es posible que conozco y conozco el segundo factor de autenticación y tengo las nociones básicas de ataques informáticos.

Parece un ataque de phishing¿tu que crees? Porque claro no voy a seguir hasta el final para comprobarlo. Al menos le he hecho perder un poco de tiempo, he marcado sus correos como no deseados o spam y le he denunciado en Gmail como ataque de phishing que no sé si servirá de algo o será suficiente para que Google tome alguna acción.

Fin.

Cómo denunciar el intento o ataque informático

Cómo comentaba en el artículo nociones básicas para detectar un ataque y evitarlo en caso de ser víctima de un ataque conviene denunciarlo. La unidad de delitos informáticos de los diferentes cuerpos de policía y un perito judicial informático seguro que os podría contar cientos de casos, pero seguramente el mejor consejo que den sea evitar ser víctima de un ataque informático. Ellos están para ayudar, proteger, minimizar daños, prevenir nuevos delitos, obtener pruebas y poner a disposición de la justicia a delincuentes pero muchas veces tras haber ocurrido los hechos el grave daño causado ya no es reparable. Y a veces les será muy difícil por estar los delincuentes en otros países. Muchos ataques informáticos como este ejemplo no son difíciles de detectar con las nociones básicas.

En los términos y condiciones del correo electrónico de Gmail no permite utilizarlo para realizar actividades ilegales incluyendo el phishing y ofrecen herramientas para denunciarlo, desde el propio Gmail y desde páginas específicas. Para denunciar una cuenta de correo que esté siendo utilizada para realizar actividades ilegales es posible tomar dos medidas, una marcar el correo como spam que Gmail tiene en cuenta, si son varios usuarios lo que lo hacen los correos del remitente a los usuarios les llegará a la carpeta de spam en vez de a la bandeja de entrada. La segunda opción es denunciar un mensaje como suplantación de identidad, aunque en realidad el Gatico Biever no me ha enviado el enlace de phishing.

En caso de recibir el enlace es posible además denunciar la página de phishing para que esta sea incluida en la lista negra de páginas identificadas maliciosas. Supongo una persona que trabaje para Google analizará estas peticiones y en caso de corroborarlo la página será añadida a la lista negra. Esta lista negra es utilizada por los navegadores para mostrar un mensaje de advertencia cuando un usuario intente entrar en ella, poniendo sobre aviso al usuario y aconsejando no entrar.

Minimizar daños de posibles ataques informáticos

Nadie está exento de ataques, ni alguien como yo que tiene conocimientos en informática y conozco las nociones básicas de los ataques, que inicialmente me resultó extraño el correo pero que hasta bastante avanzada la conversación con unos cuantos correos electrónicos enviados no empecé a realmente sospechar.

Por ello conviene tomar una serie de medidas como establecer límites transferencias y tarjeta de crédito más bajos que los que establecen por defecto los bancos que suelen ser muy generosos, activar el segundo factor de autenticación para que aunque roben las credenciales de una cuenta evitar el ataque o permitirlo únicamente durante un breve periodo de tiempo si la página de phishing fuera tan avanzada como para estar preparada para obtener también el segundo factor de autenticación.

En una de estas situaciones de ataque informático conviene que el atacante sepa lo menos posible de uno, por ello conviene proteger tu privacidad y minimizar la información tuya se puede encontrar con una búsqueda en internet.

No hay otra opción de que quede impune, si es un delincuente y parece serlo por los varios indicios va a continuar haciendo su actividad y algún usuario más incauto sea su víctima, está claro que si realizan esta actividad es porque obtienen algún beneficio. La conclusión en cualquier caso es, se bueno pero ten un poco de joputismo para conocer a los malos, hay una buena cantidad de joputas malos por ahí.

Arragonán: Píldora. Acceder a variables de entorno desde plantillas Thymeleaf

$
0
0

Es una buena práctica depender de variables de entorno para las configuraciones, tanto secretos como cualquier otra configuración que puede cambiar entre los entornos de despliegue de nuestro software. De ese modo tenemos control granular de cada configuración en cada despliegue que hagamos, y en caso de tener que cambiar alguna configuración no es necesario hacer ningún commit en nuestro repositorio.

A veces es algo que hay que montar un poco más a mano, pero trabajando con Spring Boot es algo que ya está resuelto y da flexibilidad al respecto. A nivel del código de infraestructura en código dependiente de Spring simplemente usando la anotación @Value ya nos inyectará el valor que haya en el application context.

Lo que hasta hace poco no había tenido que resolver es acceder a esas variables de entorno directamente desde plantillas de Thymeleaf, en este caso para evitar tener hardcoded la configuración de Firebase Authentication.

Buscando información encontré que, como parte de la integración con Spring, es posible acceder a los beans del application context utilizando @ en las plantillas.

Así que podemos acceder al bean que representa el Environment, por ejemplo:

${@environment.getProperty("FIREBASE_API_KEY")}

Variable not found: Enlaces interesantes 462

$
0
0
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada, obviamente muy condicionados por la oleada de lanzamientos de nuevas versiones de casi todo. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin / .NET MAUI

    Publicado en Variable not found.

    Variable not found: Generación de rutas con parámetros de query string en Blazor 6

    $
    0
    0
    Blazor

    Hasta Blazor 6, daba la impresión de que la query string era un ciudadano de segunda clase en el sistema de routing, pues no se ofrecían mecanismos sencillos para la obtención de parámetros suministrados a través de esta vía, ni tampoco para la generación de URI que los utilizaran. De hecho, estas tareas teníamos que solucionarlas manualmente, aunque fuera con ayuda de paquetes externos como Microsoft.AspNetCore.WebUtilities.

    Ya con la llegada de esta versión, Blazor incorpora de serie herramientas que nos harán esto más llevadero, como su integración con el binding o, lo que veremos en este post, la posibilidad de generar direcciones que incluyan este tipo de parámetros.

    Para generar rutas con parámetros de query string debemos utilizar el servicio NavigationManager que ya conocemos, al que se se han añadido los métodos GetUriWithQueryParameters() y GetUriWithQueryParameter() para tal fin.

    El método GetUriWithQueryParameters() genera una URI, incluyendo en su query string los parámetros que le suministremos en forma de diccionario clave-valor. En el siguiente código, por ejemplo, vemos cómo utilizar este método para generar una URI apuntando hacia la misma página actual, estableciéndole valores para tres parámetros de query stringSearch, Page y PageSize, y luego usando el método NavigateTo() para mover al usuario a ella:

    @page "/search"

    <ul>
    <li>Search: @Search</li>
    <li>Page: @Page</li>
    <li>PageSize: @PageSize</li>
    </ul>
    <button @onclick="SearchComputersClick">Search computers</button>

    @code {
    [Parameter, SupplyParameterFromQuery]
    public string? Search { get; set; }

    [Parameter, SupplyParameterFromQuery]
    public int? Page { get; set; }

    [Parameter, SupplyParameterFromQuery]
    public int? PageSize { get; set; }

    void SearchComputersClick()
    {
    var dict = new Dictionary<string, object>()
    {
    { "search", "computers" },
    { "sage", 1 },
    { "sageSize", 20 },
    };
    var uri = NavManager.GetUriWithQueryParameters(dict);
    NavManager.NavigateTo(uri);
    }
    }

    Observad también el uso de [SupplyParameterFromQuery] para recuperar estos parámetros de forma muy sencilla en las propiedades del componente.

    Aunque GetUriWithQueryParameters() por defecto tomará como punto de partida la URI de la página actual (NavigationManager.Uri), es posible indicarle una distinta usando otra de sus sobrecargas, como en el siguiente ejemplo:

    var dict = new Dictionary<string, object>()
    {
    { "search", "computers" },
    ... // Otras entradas del diccionario
    };

    // Podemos usar como base direcciones relativas al sitio:
    var uri = NavManager.GetUriWithQueryParameters("/catalog", dict);
    // O incluso direcciones absolutas externas:
    var uri = NavManager.GetUriWithQueryParameters("https://google.es", dict);
    ...

    Por supuesto, este método lidiará internamente con aspectos como la codificación URL, que se realizará de forma automática:

    var dict = new Dictionary<string, object>()
    {
    { "search", "Tom & Jerry" },
    };
    var uri = NavManager.GetUriWithQueryParameters("/catalog", dict);
    // Returns: /catalog?search=Tom%20%26%20Jerry

    El método GetUriWithParameters() no sólo añade parámetros de query string. También puede modificarlos o eliminarlos cuando partimos de una ruta que ya contenía parámetros de este tipo, aplicando una lógica bastante útil:

    • Si el diccionario añade parámetros que no se encontraban previamente en la URI original, se añaden a la dirección resultante:
    var dict = new Dictionary<string, object>()
    {
    { "search", "computers" }
    };
    var initial = "/catalog";
    var uri = NavManager.GetUriWithQueryParameters(initial, dict);
    // uri => /catalog?search=computers
    • Si la URL original incluye parámetros que no son sobrescritos en el diccionario, se mantienen:
    var dict = new Dictionary<string, object>()
    {
    { "page", "12" }
    };
    var initial = "/catalog?search=computers";
    var uri = NavManager.GetUriWithQueryParameters(initial, dict);
    // uri => /catalog?search=computers&page=12
    • Si la URI original incluye parámetros que son sobrescritos en el diccionario, se machaca el valor:
    var dict = new Dictionary<string, object>()
    {
    { "search", "computers" },
    { "page", "12" },
    };
    var initial = "/catalog?search=tv&page=1&pageSize=20";
    var uri = NavManager.GetUriWithQueryParameters(initial, dict);
    // uri => /catalog?search=computers&page=12&pageSize=20
    • Si la URI original incluye parámetros que son establecidos con valores nulos en el diccionario, se eliminan de la query string:
    var dict = new Dictionary<string, object>()
    {
    { "page", null },
    { "pageSize", null}
    };
    var initial = "/catalog?search=computers&page=1&pageSize=20";
    var uri = NavManager.GetUriWithQueryParameters(initial, dict);
    // uri => /catalog?search=computers

    Por último, cabe destacar que, para evitar el uso de un diccionario cuando únicamente queremos modificar uno de los parámetros, podemos utilizar el método GetUriWithQueryParameter():

    <button @onclick="IncrementPage">Next page</button>
    @code {
    [Parameter, SupplyParameterFromQuery]
    public int Page { get; set; }

    void IncrementPage()
    {
    Page++;
    // Actualizamos solo el parámetro "page", dejando el resto intacto:
    var uri = NavManager.GetUriWithQueryParameter("page", Page);

    // Y navegamos a la nueva URI:
    NavManager.NavigateTo(uri);
    }

    }

    Publicado en Variable not found.

    Variable not found: Enlaces interesantes 463

    $
    0
    0
    Enlaces interesantes

    Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

    Por si te lo perdiste...

    .NET Core / .NET

    ASP.NET Core / ASP.NET / Blazor

    Azure / Cloud

    Conceptos / Patrones / Buenas prácticas

    Data

    Machine learning / IA / Bots

    Web / HTML / CSS / Javascript

    Visual Studio / Complementos / Herramientas

    Xamarin / .NET MAUI

    Otros

    Publicado en Variable not found.

    Variable not found: Cómo evitar que entren argumentos nulos en métodos de C#: un recorrido histórico (y lo que nos trae el futuro)

    $
    0
    0
    .NET

    Estamos muy acostumbrados a comenzar nuestros métodos realizando comprobaciones para evitar que pasen a nuestro código valores nulos que pudieran romper la aplicación.

    Desde el principio de los tiempos, estas guardas han presentado el siguiente aspecto:

    public class MyService
    {
    public void MyMethod(object first, object second)
    {
    if(first == null)
    {
    throw new ArgumentNullException("first");
    }
    if(second == null)
    {
    throw new ArgumentNullException("second");
    }
    // ...
    }
    }

    ¿Todo bien, verdad? El código es aparentemente correcto y fácil de comprender, pero... ¡demasiado extenso! Hemos consumido casi diez líneas de código sólo realizando comprobaciones de "fontanería", y ni siquiera hemos empezado a plantear la funcionalidad real del método.

    Afortunadamente, con el tiempo C# ha ido evolucionando y mejorando sucesivamente este escenario tan frecuente.

    C# 6: el operador nameof

    Aunque no iba en la línea de simplificar el código, el operador nameof, introducido en C# 6, permitió solucionar un pequeño problema que tenían esas comprobaciones, potencial causante de problemas o confusiones. Estábamos creando una sutil y frágil dependencia entre el nombre del parámetro a nivel de código y la cadena que estamos enviando al constructor de la excepciónArgumentNullException:

    if(first == null) 
    {
    throw new ArgumentNullException("first");
    }

    Esto se puede entender rápidamente si refactorizamos el método para renombrar el parámetro first a one. El código resultante sería el siguiente, donde podemos ver que el valor enviado al instanciar la excepción no se corresponde con el nombre real del parámetro, pues al tratarse de una cadena de texto no se ha visto afectada por el renombrado:

    public void MyMethod(object one, object second)
    {
    if(one == null)
    {
    throw new ArgumentNullException("first"); // Debería ser "one"!
    }
    ...
    }

    Si bien no es un error, ciertamente podría despistar al ver la excepción, pues haría referencia a un parámetro inexistente (o, en el peor de los casos, a un parámetro incorrecto):

    Unhandled exception. System.ArgumentNullException: Value cannot be null. Parameter name: first

    El operador nameof permite obtener en tiempo de ejecución el nombre asignado a nivel de código fuente a cualquier tipo de elemento (variables, parámetros, propiedades, métodos, etc.), de forma que evitamos estas dependencias:

    public class MyService
    {
    public void MyMethod(object first, object second)
    {
    if(first == null)
    {
    throw new ArgumentNullException(nameof(first));
    }
    if(second == null)
    {
    throw new ArgumentNullException(nameof(second));
    }
    // ...
    }
    }

    Bueno, hemos mejorado en algo, pero seguimos teniendo que escribir demasiado, ¿verdad? Por suerte, C# 7 no tardó en llegar :)

    C# 7: expresiones throw

    El compilador de C# 7 comenzó a mirar las instrucciones throw con otros ojos, tratándolas a todos los efectos como si fueran expresiones, gracias a la introducción de las throw expressions.

    Recordemos que, en la práctica, esta característica permite introducir un throw en cualquier punto del código donde pueda ir una expresión, como en el siguiente ejemplo:

    public static int Divide(int a, int b)
    {
    return a / (b != 0 ? b: throw new ArgumentOutOfRangeException(nameof(b)));
    }

    Pues bien, uniendo esto al null coalescing operator (??) introducido años atrás, en los tiempos de C# 2, permite simplificar considerablemente el código de comprobación de nulos:

    public class MyService
    {
    public void MyMethod(object first, object second)
    {
    first = first ?? throw new ArgumentNullException(nameof(first));
    second = second ?? throw new ArgumentNullException(nameof(second));
    // ...
    }
    }

    Vamos mejorando, pero aún el lenguaje podía darnos algo más...

    C# 8: null coalescing assignment

    No soy capaz de traducir el nombre de esta característica, pero intentaré explicar para qué sirve 😁. Suponed un código como el siguiente, que seguro que habéis implementado más de una vez, en el que asignamos una variable sólo si ésta contiene un nulo:

    // Usando un if:
    if(myObject == null)
    {
    myObject = new MyClass();
    }

    // O bien, usando el operador "??":
    myObject = myObject ?? new MyClass();

    El null coalescing operator permite asignar una variable cuando ésta sea null en un único paso:

    myObject ??= new MyClass();

    Ahora, si recordamos el punto en el que C# 7 dejó nuestro código de comprobación de argumentos nulos, vemos que la idea puede encajar bastante y ayudarnos a simplificarlo aún más:

    public class MyService
    {
    public void MyMethod(object first, object second)
    {
    first ??= throw new ArgumentNullException(nameof(first));
    second ??= throw new ArgumentNullException(nameof(second));
    // ...
    }
    }

    Parece difícilmente mejorable... ¿o no?

    .NET 6: empoderando ArgumentNullException

    Con .NET 6/C# 10 nos llega un interesante método estático en la clase ArgumentNullException que simplifica aún más el código necesario para lanzar esa excepción si el valor recibido es nulo.

    public class MyService
    {
    public void MyMethod(object first, object second)
    {
    ArgumentNullException.ThrowIfNull(first);
    ArgumentNullException.ThrowIfNull(second);
    // ...
    }
    }

    Imposible de mejorar, ¿verdad? Después veremos que no ;)

    En cualquier caso, esta mejora es posible gracias al uso de otra novedad de C# 10, el atributo [CallerArgumentExpression]. A esto dedicaremos un post en el futuro, pero de momento basta con saber que es un atributo al estilo de [CallerMemberName], [CallerFilePath] y [CallerLineNumber], introducidos en C# 5, cuyo objetivo es obtener información sobre el consumidor de un método.

    Podemos ver su utilización en el código fuente de ArgumentNullException, e intuir cómo funciona:

    public class ArgumentNullException : ArgumentException
    {
    ...
    public static void ThrowIfNull(
    [NotNull] object? argument,
    [CallerArgumentExpression("argument")] string? paramName = null)
    {
    ...
    }
    }

    Si realizamos una invocación como ArgumentNullException.ThrowIfNull(first), el valor recibido en argument será el valor de first, mientras que en paramName recibiremos la cadena "first". Esto permitirá mostrar el error exactamente con la expresión utilizada en el punto de la llamada.

    .NET 6 / C# 10: doble salto mortal con los global using static

    Pues sí, aunque suene un poco a feature abuse, podemos darle una vuelta más al asunto haciendo uso de las directivas globales. Aunque en un post ya vimos cómo usar usings globales para importar espacios de nombres, también podemos utilizarla para facilitar el acceso a miembros estáticos.

    En la práctica, podemos añadir el cualquier archivo del proyecto una directiva como la siguiente (aunque también podemos hacerlo en el .csproj):

    global using static System.ArgumentNullException

    Y de esta forma, podemos reducir aún más nuestro código de partida:

    public class MyService
    {
    public void MyMethod(object first, object second)
    {
    ThrowIfNull(first);
    ThrowIfNull(second);
    // ...
    }
    }

    Esto ya sí que no lo mejora nadie. ¿O sí?

    C# vNext: simplificando el chequeo de argumentos nulos

    Se está cociendo una nueva mejora en el lenguaje que probablemente será el golpe definitivo al código de chequeo de nulos al inicio de nuestros métodos.

    Aunque de momento está en desarrollo y las cosas podrían cambiar, las comprobaciones simplificadas de argumentos nulos o Simplified Null Argument Checking, nos permitirán eliminar totalmente estas comprobaciones.

    En su lugar, simplemente definiremos los parámetros que queremos comprobar usando una exclamación, de la siguiente forma:

    public class MyService
    {
    public void MyMethod(object first!!, object second!!)
    {
    // ...
    }
    }

    ¡Voila! El único hecho de añadir esas exclamaciones al nombre del parámetro hará que en tiempo de ejecución se comprueben los valores, y se lance de forma automática una excepción ArgumentNullException cuando el valor sea nulo.

    Fijaos que las exclamaciones están en el parámetro, no en su tipo: esto es así porque se trata de que el sistema añada una comprobación en tiempo de ejecución, pero no afecta al tipo del parámetro.

    Punto extra: recordad que usar "==" no es la mejor forma de comprobar los nulos

    Si aún con estas novedades del lenguaje y la plataforma preferís utilizar la clásica sentencia if para comprobar los nulos, es interesante que tengáis en cuenta dos cosas.

    En primer lugar, ya hablamos hace tiempo de usar el operador "==" para comparar con valores nulos no era la forma más correcta de hacerlo, pues dicho operador podía ser sobrecargado para otorgarle un comportamiento distinto del esperado.

    De hecho, la forma recomendable de comprobar la nulidad de un objeto es utilizar el operador is:

    if(myObj is null)
    {
    ...
    }

    De la misma forma, si queremos comprobar justamente lo contrario, es decir, que un objeto no sea nulo, podemos aprovechar los patrones combinacionales introducidos por C# 9 y hacerlo de esta forma tan elegante:

    if(myObj is not null)
    {
    ...
    }

    ¡Y esto es todo! Espero que este recorrido por las diferentes opciones que tenemos y tendremos para evitar la entrada de argumentos nulos en los métodos os haya resultado interesante :)

    Publicado en Variable not found.

    Arragonán: Documental sobre Squads

    $
    0
    0

    Squads es un documental de Invision sobre el popularizado término squads, en el que se explica su origen y se muestran unas pinceladas de cómo trabajan algunos equipos que crean productos de digitales.

    Mi resumen sobre el término sería algo como tener equipos multidisciplinares donde se mezclan personas con habilidades complementarias que estén alineadas para alcanzar un objetivo común, o como mínimo aspirar a ello.

    El documental se centra principalmente en la parte de descubrimiento y diseño de producto (siendo Invision una compañía de diseño tampoco sorprende :)). Aparecen personas de compañías conocidas mundialmente como Atlassian, Airbnb, Youtube… y algunas startups de menor tamaño. Además de Jeff Sutherland, uno de los creadores de Scrum; y Henrik Kniberg, el de los famosos vídeos de Spotify Engineering Culture que tanto se viralizaron y terminaron en el boom del “modelo spotify” que se ha intentado replicar tantas veces, al parecer sin demasiado éxito.

    Creo que es un documental interesante para cualquiera que trabaje en el mundo de producto digital, sea cual sea su perfil. Aunque también creo que idealiza y simplifica el conseguir trabajar de ese modo.

    Digo esto porque, aunque creo que tener equipos multidisciplinares es la mejor estrategia para construir producto (que los llamen squads, células, scrum teams… es irrelevante), no es algo que ocurra diciéndole a un grupo de personas que tienen que trabajar en lo mismo y eso haga que se alineen mágicamente. Hay que trabajarlo e iterarlo, y aún así puede que nunca se consiga convertir a un grupo de personas en un equipo.


    Blog Bitix: Validar documentos JSON con JSON Schema

    $
    0
    0

    Los documentos JSON son una forma de intercambiar información entre aplicaciones. Como en cualquier intercambio de información es conveniente validar los datos recibidos antes de realizar ninguna acción. En Java dependiendo de la librería o framework utilizada aunque los datos se transmiten en formato JSON estos son transformados y recibidos como objetos Java en los cuales se realizan validaciones de tipos y conversiones de tipos y restricciones a los valores con Bean Validation o Spring Validation. La especificación JSON Schema permite definir un esquema para los documentos JSON independiente del lenguaje con la que realizar validaciones y realizar las validaciones a través de implementaciones en los diferentes lenguajes de programación incluido Java.

    Java

    Una tarea fundamental en toda aplicación es validar los datos de entrada. Validar los datos evita errores al procesar los datos, generar datos erróneos como resultado o realizar acciones en base a datos no válidos con consecuencias como realizar acciones no deseadas o crear inconsistencias en la base de datos. También hay que validar los datos por motivos de seguridad.

    Los datos de entrada de un programa se proporcionan en función de la naturaleza de la aplicación, en una aplicación web o REST es a través de los datos de la petición, en una aplicación que procesa mensajes de servicios como Kafka o RabbitMQ los datos se incluyen en los datos del mensaje y en una aplicación de procesos batch los datos quizá estén en archivos.

    Los formatos más comunes para el intercambio de datos son XML, JSON y CSV. El formato de documentos XML permite comprobar está bien formado en cuanto a balanceo de etiquetas junto a otros requerimientos, los esquemas XML permiten validar además si un documento XML cumple con el esquema incluyendo las etiquetas requeridas. JSON es una especificación que de por si no define ningún esquema, esto hace que los documentos JSON puedan tener cualesquiera datos mientras utilicen una sintaxis correcta o tengan un formato correcto. Sin embargo, en la validación de datos el que un documento JSON tenga una sintaxis correcta no es suficiente que se considere válido. Un esquema permite definir que un documento incluya ciertas propiedades, que estás se ajusten a unos valores predeterminados, que cumplan ciertas reglas de validación como un tipo o rango de valores.

    La especificación JSON Schema es el equivalente para los documentos JSON de XML Schema para los documentos XML. JSON Schema permite validar que un documento JSON se ajusta a un esquema conteniendo los datos y valores definidos en el esquema.

    Contenido del artículo

    La especificación JSON Schema

    La especificación de JSON Schema tiene varias definiciones formales y versiones. En la guía de inicio paso a paso se incluye una descripción más sencilla y práctica para un primer inicio.

    Un esquema de JSON contiene a qué versión de la especificación se ajusta, el identificador o la ubicación del esquema, un título, una descripción y el tipo de objeto del documento raíz. Además define qué propiedades junto con sus tipos ha de contener el documento JSON al que se aplica, cuáles de esas propiedades son requeridas y las validaciones sobre los datos como restricciones en los valores de los datos o elementos de un array. Además de propiedades un documento permite la anidación de estructuras en las que también se definen que propiedades contienen y cuáles son requeridas. Finalmente, un esquema JSON permite referenciar un esquema JSON externo.

    En el siguiente esquema $schema define la versión del esquema que implementa, $id define el identificador del esquema. Las propiedades title, description proporcionan una descripción del esquema y type el tipo de objeto raíz. En la propiedad properties se definen las propiedades del documento JSON y en la propiedad required cuáles de esas propiedades son requeridas. En la propiedad dimensions están las estructuras JSON anidadas. Y con la propiedad $ref se referencia otro esquema JSON.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    
    {    "$schema":"https://json-schema.org/draft/2020-12/schema",    "$id":"https://example.com/product.schema.json",    "title":"Product",    "description":"A product from Acme's catalog",    "type":"object",    "properties":{      "productId":{        "description":"The unique identifier for a product",        "type":"integer"      },      "productName":{        "description":"Name of the product",        "type":"string"      },      "price":{        "description":"The price of the product",        "type":"number",        "exclusiveMinimum":0      },      "tags":{        "description":"Tags for the product",        "type":"array",        "items":{          "type":"string"        },        "minItems":1,        "uniqueItems":true      },      "dimensions":{        "type":"object",        "properties":{          "length":{            "type":"number"          },          "width":{            "type":"number"          },          "height":{            "type":"number"          }        },        "required":[          "length",          "width",          "height"        ]      },      "warehouseLocation":{        "description":"Coordinates of the warehouse where the product is located.",        "$ref":"https://example.com/geographical-location.schema.json"      }    },    "required":[      "productId",      "productName",      "price"    ]}
    product.schema.json
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    {    "$id":"https://example.com/geographical-location.schema.json",    "$schema":"https://json-schema.org/draft/2020-12/schema",    "title":"Longitude and Latitude",    "description":"A geographical coordinate on a planet (most commonly Earth).",    "required":[      "latitude",      "longitude"    ],    "type":"object",    "properties":{      "latitude":{        "type":"number",        "minimum":-90,        "maximum":90      },      "longitude":{        "type":"number",        "minimum":-180,        "maximum":180      }    }}
    geographical-location.schema.json
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    {"productId":1,"productName":"An ice sculpture","price":12.5,"tags":[    "cold",    "ice"],"dimensions":{    "length":7,    "width":12,    "height":9.5},"warehouseLocation":{    "latitude":-78.75,    "longitude":20.4}}
    product.json
    1
    2
    
    {}
    product-invalid.json

    Librerías JSON Schema en Java

    Hay varias librerías Java que implementan validación de JSON con la especificación de JSON Schema, junto a otras implementaciones en otros lenguajes. De entre las implementaciones Java una de ellas es JSON Schema Validator de networknt en la que los errores que se detectan son devueltos en una estructura de datos en vez de lanzar una excepción en caso de que la validación falle.

    Otra de sus funcionalidades es que permite hacer una correspondencia entre los identificadores de los esquemas JSON a recursos locales, útil en caso de que los esquemas no estén publicados en sus direcciones, en aplicaciones en las que no tengan conexión a internet o no se desea que estas realicen conexiones externas.

    Hay que tener en cuenta que varias de estas librerías están implementadas por personas sin seguramente el respaldo de una organización, hay que tenerlo en cuenta como criterio de decisión en el caso de añadir como dependencia de un proyecto una de las implementaciones.

    Ejemplo con Java de validar un JSON con JSON Schema

    Este es un ejemplo que a partir de un documento JSON se valida que cumple el esquema contra el que se valida. En el caso de que el documento JSON no cumpla el esquema se devuelven los errores como resultado del método de validación, en el caso del ejemplo los errores son emitidos a la salida estándar donde se aprecia que en el caso de la validación del JSON inválido faltan las tres propiedades requeridas.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    packageio.github.picodotdev.blogbitix.jsonschema;importjava.net.URI;importjava.util.Map;importjava.util.Set;importcom.fasterxml.jackson.databind.JsonNode;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.networknt.schema.JsonSchema;importcom.networknt.schema.JsonSchemaFactory;importcom.networknt.schema.SpecVersion;importcom.networknt.schema.ValidationMessage;publicclassMain{    publicstaticvoidmain(String[]args)throwsException{        Map<String,String>urlMappings=Map.of("https://picodotdev.github.io/blog-bitix/misc/json/product.schema.json","resource:/product.schema.json",                "https://picodotdev.github.io/blog-bitix/misc/json/geographical-location.schema.json","resource:/geographical-location.schema.json");        ObjectMappermapper=newObjectMapper();        JsonSchemaFactoryfactory=JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909))                .objectMapper(mapper)                .addUriMappings(urlMappings)                .build();        JsonSchemaschema=factory.getSchema(URI.create("resource:/product.schema.json"));        {            JsonNodejson=mapper.readTree(Main.class.getResourceAsStream("/product.json"));            Set<ValidationMessage>errors=schema.validate(json);            System.out.printf("Valid JSON errors: %d5n",errors.size());        }        {            JsonNodejson=mapper.readTree(Main.class.getResourceAsStream("/product-invalid.json"));            Set<ValidationMessage>errors=schema.validate(json);            System.out.printf("Valid JSON errors: %d%n",errors.size());            errors.stream().forEach(it->{                System.out.printf("Type: %s%n",it.getType());                System.out.printf("Message: %s%n",it.getMessage());            });        }    }}
    Main.java
    1
    2
    3
    4
    5
    6
    7
    8
    
    Valid JSON errors: 0
    Invalid JSON errors: 3
    Type: required
    Message: $.productId: is missing but it is required
    Type: required
    Message: $.productName: is missing but it is required
    Type: required
    Message: $.price: is missing but it is required
    System.out

    Otras formas de validación con Bean Validation y Spring Validation

    Otra forma de validar un JSON es cargarlo en un objeto Java y validar el objeto con Bean Validation o Spring Validation. La diferencia en este caso respeto a JSON Schema es que Bean Validation y Spring Validation es una solución específica de Java, requiere cargar los datos en objetos y más importante no se define ningún esquema sino que el esquema está implícito en las validaciones ya se definan con anotaciones o con validadores personalizados.

    Terminal

    El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
    ./gradlew run

    Variable not found: Enlaces interesantes 464

    $
    0
    0
    Enlaces interesantes

    Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

    Por si te lo perdiste...

    .NET Core / .NET

    ASP.NET Core / ASP.NET / Blazor

    Azure / Cloud

    Conceptos / Patrones / Buenas prácticas

      Web / HTML / CSS / Javascript

        Xamarin / .NET MAUI

          Publicado en Variable not found.

          Una sinfonía en C#

          $
          0
          0

          Hola a todos!

          Voy a hacer una serie de post sobre oAuth2, intentando aclarar cada concepto paso a paso.

          La idea es explicar lo mejor posible todos los conceptos (al menos los más importantes) para que se entienda lo mejor posible, es un tema bastante complejo pero también muy importante y en lo personal creo que todo desarrollador debería comprenderlo bien.

          También veremos OpenID Connect como parte de esta serie ya que están muy relacionados.

          A fines prácticos vamos a hablar siempre de oAuth2.

          ¿Qué es oAuth2?

          Es un protocolo standard, de autorización, así que vamos a dedicar este primer post a aclarar esto: ¿Qué es oAuth?

          Autorización vs autenticación

          Autorizado es que tiene permisos para hacer algo.

          Autenticado es que se puede verificar quién es.

          Como vemos no es lo mismo, de hecho son cosas separadas.

          Estar autorizado

          El ejemplo más claro para mí es un ticket de cine, el mismo no tiene nombre, ni dice nada sobre la persona que lo compró, pero autoriza a quien lo tenga a hacer algo, en este caso a entrar a ver una película, y solo lo autoriza a hacer eso. Es importante tener en cuenta que no importa si yo compré el ticket, quien lo tenga podrá entrar al cine aunque lo haya encontrado en el suelo.

          Podemos tener autorizaciones que nos permitan hacer más cosas, pero si hablamos de autorización el simple hecho de poseer el ticket (vamos a llamarlo Token) nos habilita a hacer algo independientemente de nuestra identidad, y de hecho, quien nos autorice no necesita saber nada sobre nosotros, solo que tenemos ese Token (en este caso en forma de un ticket de cine)

          Estar autenticado

          En este caso la autenticación verifica que somos quienes decimos ser, pero no implica que estemos autorizados. Un ejemplo puede ser un documento, permite verificar datos propios pero no implica que tenga permisos de hacer algo, por ejemplo, pasar una frontera, o volviendo al ejemplo anterior ingresar al cine, si no tengo un ticket no puedo entrar al cine.

          Se pueden mezclar autorización y autenticación

          Es posible que en algunos casos el hecho de verificar nuestra identidad nos de acceso, porque en el mundo real los conceptos son menos claros, pero para hablar de oAuth y OIDC (OpenID Connect) vamos a diferenciarlos, ya que

          oAuth es un protocolo de autorización

          OIDC es un protocolo de autenticación

          Algunas aclaraciones

          Por simplificar, a veces se llama OIDC cuando tenemos ambas cosas, oAuth y OIDC porque este último es una extensión del primero, pero siendo rigurosos OIDC provee una capa de autenticación a oAuth que es un protocolo de autenticación.

          ¿Qué problema intenta solucionar?

          Sin entrar en historias largas, el problema que intentams solucionar es:

          Autorizar a un cliente, sin exponer credenciales ni identidad, dando un acceso limitado a solo un conjunto de recursos por un tiempo.

          Un ejemplo puede ser cuando hacemos login con Twitter (o Facebook, etc.) para poder usar otra aplicación, por ejemplo Adobe. Estamos dando acceso a parte de nuestros datos a un cliente (el sitio de Adobe)

          Vamos a ver un poco de vocabulario

          ¿Quién es un cliente?

          Un cliente será cualquier aplicación que quiera tener acceso a un recuso. Nunca será una persona física. Algunos ejemplos:

          • Un sitio web
          • Un frontend que quiere acceder a una API
          • Un backend que accede a otro backend

          ¿Qué son recursos?

          Llamamos recursos a todo aquello a lo que podemos dar un nivel de acceso:

          • Una aplicación
          • Una parte de la aplicación
          • Una API
          • Un sistema
          • Un conjunto de información
          • Etc.

          ¿Y quién se encarga de dar acceso a los clientes sobre esos recursos?

          Esta entidad se llama Identity provider o IDP (por ejemplo Facebook), es quien conoce a los usuarios y otorga permisos a los clientes (el sitio de Adobe) a acceder a mi información (el recurso). En Instagam podemos tener la opción de que una publicación se vea también en Twitter, esto es un buen ejemplo de oAuth.

          Algunos ejemplos de uso de oAuth

          Instagram quiere publicar en Twitter en nuestro nombre, bien, entonces:

          • Instagram es el cliente
          • La API de Twitter es el recurso
          • Twitter es también el IDP (porque somos usuarios de Twitter)

          Entonces, Twitter nos conoce como usuarios y también a Instagram como cliente, y simplemente le da acceso a la API de publicación en nuestro nombre por un tiempo limitado a través de un Token. De este modo solucionamos muchos problemas.

          Lo mismo pasa cuando queremos importar contactos de una red social a otra, al final, concentimos acceso a un recurso que es nuestro (nuestros contactos, nuestro timeline, es así que nuestro rol es de Resource owner) a un cliente (Instagram o quién sea)

          Identity provider

          El IDP puede no ser quien gestione los recusos, solo quien gestiona los accesos, por ejemplo en Google tenemos un único login (IDP) con el cual accedemos a muchos servicios (Recursos) que no están en el mismo dominio (y de hecho, no son la misma aplicación ni nada)

          Nota: es por eso que en 2021 hubo un fallo global en los servicios de Google porque falló el servicio de autenticación (IDP) que todos los otros servicios usan.

          Repasando el vocabulario

          • Recurso: Un elemento al que se puede otorgar acceso, como una API, un dato, una aplicación, etc.
          • Token: Un elemento que sirve para otorgar el acceso, en forma de un conjunto de caracteres (un GUID, un número, o algo más complejo como un JSON Web Token), suelen tener un acceso limitado a ciertos recursos por un tiempo limitado.
          • IDP: Es quien otorga Tokens, quien conoce a los usuarios y a los clientes.
          • Cliente: Una aplicación que quiere acceder a un recurso.
          • Resource Owner: El propietario de los recursos, no siempre son personas, en el caso de que el recurso sea una API el RO será la aplicación.

          Bien, en la próxima continuamos hablando sobre flujos de autenticación. Nos leemos.

          Variable not found: El atributo CallerArgumentExpression, o cómo conocer las expresiones usadas como argumentos en llamadas a un método en C#

          $
          0
          0
          .NET

          Cuando aparece una nueva versión de C# o .NET, los titulares de las noticias, tweets y posts suelen girar en torno a las novedades más destacadas, aquellas que suponen cambios importantes respecto a versiones anteriores. Pero es habitual que, aparte de éstas, se añadan otras características más pequeñas que muchas veces pasan desapercibidas.

          Esto es lo que ocurre con al atributo [CallerArgumentExpression], una joyita de C#10 que puede ayudarnos a hacer más descriptivos los mensajes de error y trazas que guardamos cuando aparece un error en nuestras aplicaciones.

          Y para entenderlo bien, comencemos viendo un ejemplo de la situación previa a la aparición de este atributo. Creemos una nueva aplicación de consola .NET 6 e introducimos el siguiente código en Program.cs; no hace falta nada más, gracias nuevas características de C# 10 como top level statements e implicit usings:

          Console.WriteLine(Divide(10, 5));
          Console.WriteLine(Divide(10, DateTime.Now.Second % 2));

          int Divide(int a, int b)
          {
          if (b == 0)
          throw new ArgumentOutOfRangeException(nameof(b), "El divisor no puede ser cero");
          return a / b;
          }

          Como podéis intuir, la idea es que la aplicación explote cuando la ejecutemos en un segundo par. Si corremos la aplicación y todo va bien, el resultado sería el siguiente:

          C:\Projects\Test>dotnet run
          2
          10
          C:\Projects\Test>_

          Sin embargo, si la ejecutamos en un segundo par, el resultado obtenido será el mostrado a continuación:

          C:\Projects\Test>dotnet run
          2
          Unhandled exception.
          System.ArgumentOutOfRangeException: El divisor no puede ser cero (Parameter 'b')
          at Program.<<Main>$>g__Divide|0_0(Int32 a, Int32 b) in C:\Projects\Test\Program.cs:line 6
          at Program.<Main>$(String[] args) in C:\Projects\Test\Program.cs:line 2

          C:\Projects\Test>_

          La excepción deja bien claro de lo que se trata, pues ofrece información textual del problema y el parámetro cuyo valor es inválido. Incluso, examinando el stack trace, podemos llegar a ver en cuál de las dos llamadas se ha introducido el problema. Sin embargo, si simplemente disponemos del mensaje de error, nos costará algo más de trabajo ver el origen del problema.

          Y aquí es donde entra en juego [CallerArgumentExpression], un atributo que podemos aplicar a un parámetro string del método para que el framework lo pueble automáticamente con la expresión del código fuente que ha generado el valor enviado al método. What?

          Reformulemos el método Divide() para hacer uso de esta característica y seguro que lo vemos más claro:

          int Divide(int a, int b, [CallerArgumentExpression("b")]string? divisorExpression = null)
          {
          if (b == 0)
          throw new ArgumentOutOfRangeException(nameof(b),
          $"El divisor no puede ser cero. Expresión: {divisorExpression}"
          );

          return a / b;
          }

          Fijaos que el parámetro divisorExpression (o como le queramos llamar) tiene null como valor por defecto, para no hacer obligatorio su uso en la llamada al método, y con su atributo [CallerArgumentExpression("b")] indicamos al framework que debe introducir aquí la expresión usada para enviar el valor al parámetro b.

          Si ahora ejecutamos en el segundo apropiado, veremos que el mensaje de error es más claro, pues incluye la expresión cuya evaluación provocó el problema:

          C:\Projects\Test>dotnet run
          2
          Unhandled exception.
          System.ArgumentOutOfRangeException: El divisor no puede ser cero.
          Expresión: DateTime.Now.Second % 2 (Parameter 'b')
          at Program.<<Main>$>g__Divide|0_0(Int32 a, Int32 b, String divisorExpression)
          in C:\Projects\Test\Program.cs:line 9
          at Program.<Main>$(String[] args) in C:\Projects\Test\Program.cs:line 4

          C:\Projects\Test>_

          Así, simplemente observando el mensaje del error podríamos determinar cuál fue la causa, sin necesidad de acudir al código fuente.

          En .NET 6, podemos ver el uso de este atributo en ArgumentNullException.ThrowIfNull(), la nueva fórmula rápida para evitar la entrada de valores nulos en nuestros métodos:

          public void MyMethod(object first, object second)
          {
          ArgumentNullException.ThrowIfNull(first);
          ArgumentNullException.ThrowIfNull(second);
          // ...
          }

          Obviamente, hay que saber cuándo usarlo, porque tiene sus peligros. Dado que lo que aparece ahí es el código fuente tal cual ha sido escrito, éste podría llegar a mostrar información confidencial o importante. Imaginad este ejemplo, que aunque sea algo exagerado, creo que sirve como muestra:

          ...
          var x = Divide(100000, 345678 /* Secret key */ - y);

          Si b vale 345678, el resultado que obtendríamos por consola sería el siguiente, donde podéis ver que se muestra la expresión de la invocación, incluida la clave secreta e incluso el comentario presente en el código fuente:

          C:\Projects\Test>dotnet run
          2
          Unhandled exception.
          System.ArgumentOutOfRangeException: El divisor no puede ser cero.
          Expresión: 345678 /* Secret key */ - y (Parameter 'b')
          at Program.<<Main>$>g__Divide|0_0(Int32 a, Int32 b, String divisorExpression)
          in C:\Projects\Test\Program.cs:line 11
          at Program.<Main>$(String[] args) in C:\Projects\Test\Program.cs:line 6

          C:\Projects\Test>_

          Esta información podría quedar registrada en trazas y ser visible por cualquiera que tuviera acceso a ellas. 

          De la misma forma, si descompilamos la aplicación, en el código obtenido veremos que la expresión es incluida en la llamada, por lo que podríamos tener también acceso a esta información si usamos una herramienta de este tipo con los ensamblados de la aplicación:

          Program.<<Main>$>Eg__Divide|0_0(100000, 345678 - y, "345678 /* Secret key */ - y");

          Publicado en Variable not found.

          Una sinfonía en C#: oAuth2 paso a paso “¿Qué es oAuth?”

          $
          0
          0

          oAuth es prácticamente la opción más utilizada para securizar aplicaciones modernas por diferentes motivos, éste es el primer de una serie de post sobre oAuth2, intentando aclarar cada concepto paso a paso. Si bien es un tema bastante complejo pero también muy importante y en lo personal creo que todo desarrollador debería comprenderlo bien.

          También veremos OpenID Connect como parte de esta serie ya que están muy relacionados.

          A fines prácticos vamos a hablar siempre de oAuth2.

          ¿Qué es oAuth2?

          oAuth es un protocolo standard, de autorización, que provee flujos específicos para aplicación web, desktop, mobile y disponistivos de la vida diaría” Algo así dice su definición, así que vamos a aclarar de a poco cada concepto.

          Autorización vs autenticación

          Lo primero es diferenciar autorización de autenticación:

          Autorizado es que tiene permisos para hacer algo.

          Autenticado es que se puede verificar quién es.

          Estar autorizado

          El ejemplo más claro para mí es un ticket de cine, el mismo no tiene nombre, ni dice nada sobre la persona que lo compró, pero autoriza a quien lo tenga a hacer algo, en este caso a entrar a ver una película, y solo lo autoriza a hacer eso. Es importante tener en cuenta que no importa si yo compré el ticket, quien lo tenga podrá entrar al cine aunque lo haya encontrado en el suelo.

          El simple hecho de poseer el ticket (vamos a llamarlo Token) nos habilita a hacer algo independientemente de nuestra identidad, y de hecho, quien nos autorice no necesita saber nada sobre nosotros, solo que tenemos ese Token (en este caso en forma de un ticket de cine)

          Estar autenticado

          En este caso la autenticación verifica que somos quienes decimos ser, pero no implica que estemos autorizados. Un ejemplo puede ser un documento, permite verificar datos propios pero no implica que tenga permisos de hacer algo, por ejemplo, pasar una frontera, o volviendo al ejemplo anterior ingresar al cine, si no tengo un ticket no puedo entrar al cine por más que tenga un DNI o pasaporte. oAuth no provee mecanismos de autenticación

          Algunas aclaraciones sobre OpenID Connect (OIDC)

          Por simplificar, a veces se llama OIDC cuando tenemos ambas cosas, oAuth y OIDC porque este último es una extensión del primero, pero siendo rigurosos OIDC provee una capa de autenticación a oAuth que es un protocolo de autenticación.

          ¿Qué problema intenta solucionar oAuth?

          Sin entrar en historias largas, el problema que intentams solucionar es:

          Autorizar a un cliente, sin exponer credenciales ni identidad, dando un acceso solo un conjunto de recursos por un tiempo limitado.

          Algo de vocabulario

          Hay mucho vocabolario de oAuth y es bueno comenzar a familiarizarnos con él, comencemos con lo más básico.

          ¿Quién es un cliente?

          Un cliente será cualquier aplicación que quiera tener acceso a un recuso. Nunca será una persona física. Algunos ejemplos:

          • Un sitio web
          • Un frontend que quiere acceder a una API
          • Un backend que accede a otro backend

          ¿Qué son recursos?

          Llamamos recursos a todo aquello a lo que podemos dar un nivel de acceso:

          • Una aplicación
          • Una parte de la aplicación
          • Una API
          • Un sistema
          • Un conjunto de información
          • Una funcionalidad del protocolo
          • Etc.

          ¿Y quién se encarga de dar acceso a los clientes sobre esos recursos?

          Esta entidad se llama Identity provider o IDP (por ejemplo Facebook), es quien conoce a los usuarios y otorga permisos a los clientes (el sitio de Adobe) a acceder a mi información (el recurso).

          Algunos ejemplos de uso de oAuth

          En Instagam podemos tener la opción de que al crear una publicación se publique también en Twitter, esto es un buen ejemplo de oAuth.

          Instagram quiere publicar en Twitter en nuestro nombre, bien, entonces:

          • Instagram es el cliente
          • La API de Twitter es el recurso
          • Twitter es también el IDP (porque somos usuarios de Twitter)

          Entonces, Twitter nos conoce como usuarios y también a Instagram como cliente, y simplemente le da acceso a la API de publicación en nuestro nombre por un tiempo limitado a través de un Token. De este modo solucionamos muchos problemas.

          Lo mismo pasa cuando queremos importar contactos de una red social a otra, al final, concentimos acceso a un recurso que es nuestro (nuestros contactos, nuestro timeline, es así que nuestro rol es de Resource owner) a un cliente (Instagram o quién sea) y ese acceso lo otorga el IDP proveyendo un Token al cliente.

          Identity provider

          El IDP es el responsable de otorgar acceso, es quien conoce a los clientes y los recursos, cuando un cliete solicita acceso a un recurso el IDP le provee un Token, el Resource Provider (quien tiene el recurso, por ejemplo Twitter) verificar que ese Token es válido.

          Quien gestiona los recursos no siempre es también el IDP

          El IDP puede no ser quien gestione los recusos como hemos dicho, solo quien gestiona los accesos, por ejemplo en Google tenemos un único login (IDP) con el cual accedemos a muchos servicios (Recursos) que no están en el mismo dominio (y de hecho, no son la misma aplicación ni nada). Entonces el login central de Google es el IDP y la API de GMaps será el Resource Provider, y la misma estará separada en recursos, por ejemplo, la capacidad de buscar una dirección será un Recurso particular sobre el que podemos perdir acceso, pero tal vez no podamos hacerlo para crear puntos de interés en el mapa.

          Nota: es por eso que en 2021 hubo un fallo global en los servicios de Google porque falló el servicio de autenticación (IDP) que todos los otros servicios usan.

          Repasando el vocabulario

          • Recurso: Un elemento al que se puede otorgar acceso, como una API, un dato, una aplicación, etc.
          • Token: Un elemento que sirve para otorgar el acceso, en forma de un conjunto de caracteres (un GUID, un número, o algo más complejo como un JSON Web Token), suelen tener un acceso limitado a ciertos recursos por un tiempo limitado.
          • IDP: Es quien otorga Tokens, quien conoce a los usuarios y a los clientes.
          • Cliente: Una aplicación que quiere acceder a un recurso.
          • Resource Provider: Quien gestiona los recursos, verificar que las solicitudes de acceso de los clientes son válidas para el IDP configurado
          • Resource Owner: El propietario de los recursos, no siempre son personas, en el caso de que el recurso sea una API el RO será la aplicación, pero en caso de nuestro muro de Facebook seremos nosotros.

          Más o menos los actores se relacionan así (de modo simplificado)

          Bien, en la próxima continuamos hablando sobre Tokens. Nos leemos.

          Viewing all 2699 articles
          Browse latest View live