Hoy en día, las aplicaciones web se han convertido en parte integral de nuestras vidas, ofreciendo cómodas funciones que ahorran tiempo y simplifican las tareas cotidianas. Por ejemplo, crear cuentas en diversas plataformas es una de las acciones más frecuentes de los usuarios en los sitios web.
Esperan que este tipo de proceso sea rápido y accesible, ya sea en casa, en el trayecto al trabajo o relajándose en la playa.
Detrás de esta simplicidad se esconde una realidad más compleja. Estas operaciones suelen requerir la integración con sistemas de terceros, como los servicios de verificación de correo electrónico. Esto plantea retos relacionados con la seguridad, la continuidad de la experiencia del usuario y la protección contra ataques de intermediarios.
Para los desarrolladores, garantizar una experiencia fluida significa gestionar las interacciones entre los sistemas externos y la sesión web 4D. Esto implica mantener el contexto del usuario: recuperar datos, privilegios y el paso exacto de su viaje para completar el proceso.
¿Suena complicado? No tiene por qué serlo. Descubra cómo construir aplicaciones web robustas que se comunican de forma segura y eficiente con sistemas de terceros con 4D 20R9.
A menudo, en las aplicaciones web, la experiencia del usuario requiere varios pasos como:
Cuando se manejan inventarios de productos en un almacén
- hacer una selección de productos
- enviar la selección a un sistema de registro externo
- volver a la lista de productos en la aplicación
o
Al crear una cuenta en un sitio web
- introducir el correo electrónico + la contraseña para crear la cuenta
- validar el correo electrónico haciendo clic en un enlace recibido en un correo electrónico para finalizar la creación de la cuenta
Estos pasos requieren ir y venir con sistemas de terceros. Así, una sesión web 4D debe ser identificada de forma única en el servidor para poder ser recuperada posteriormente.
LA FUNCIÓN createOTP() EN EL OBJETO SESIÓN
El identificador de una sesión web 4D es la cookie de sesión («4DSID_AppName«). Intercambiar este valor de cookie en la red entre una aplicación web 4D y un sistema de terceros es una torpe violación de la seguridad.
Para evitarlo, en cualquier proceso web, un One-Time-Passcode(OTP) puede ser generado gracias a la nueva función createOTP() disponible en el objeto Session.
Este OTP está vinculado a esta sesión y permite recuperarlo en una petición recibida, que no recibe la cookie de sesión.
Este OTP sólo puede utilizarse una vez y puede asociarse a una duración de vida.
ejemplo
var $token : Text
$token:=Session.createOTP()
¿Cómo puedo recuperar una sesión web gracias a la OTP?
La sesión web puede recuperarse de dos maneras.
el parámetro $4DSID en una URL
La sesión web se recuperará automáticamente si la solicitud recibida contiene en el parámetro $4DSID una OTP válida correspondiente a la sesión.
ejemplo
En este ejemplo, se crea una cuenta de usuario en la clase de datos Users con la función create().
Se recibe un objeto $info con el email + contraseña. Se crea un nuevo usuario, y se almacena cierta información en la sesión, especialmente el paso actual del proceso de creación de la cuenta de usuario(Esperando el email de validación) y el ID de usuario.
Se genera una OTP correspondiente a la sesión actual. Finalmente, se devuelve una URL con esta OTP dada en el parámetro $4DSID.
// In the Users dataclass
Function create($info : Object) : Text
var $user : cs.UsersEntity
var $status : Object
var $token : Text
//A new entity of the Users dataclass is created
$user:=This.new()
$user.fromObject($info)
$status:=$user.save()
Use (Session.storage)
Session.storage.status:=New shared object("step"; "Waiting for validation email"; "email"; $user.email; "ID"; $user.ID)
End use
$token:=Session.createOTP()
return "https://my4DApp/validateEmail?$4DSID="+$token
A continuación, se envía al usuario esta URL como enlace en un correo electrónico. El prefijo URL /validateEmail es manejado por los HTTP request handlers (archivo HTTPHandlers.json).
[
{
"class": "RequestHandler",
"method": "validateEmail",
"regexPattern": "/validateEmail",
"verbs": "get"
}
]
Aquí está la función validateEmail() del singleton RequestHandler.
Function validateEmail() : 4D.OutgoingMessage
var $result:=4D.OutgoingMessage.new()
var $user : cs.UsersEntity
var $status : Object
If (Session.storage.status.step="Waiting for validation email")
$user:=ds.Users.get(Session.storage.status.ID)
$user.validated:=True
$status:=$user.save()
$result.setBody("Congratulations <br>"\
+"Your email "+Session.storage.status.email+" has been validated")
$result.setHeader("Content-Type"; "text/html")
Use (Session.storage.status)
Session.storage.status.step:="Email validated"
End use
Else
// Retrieving the session with the OTP failed
$result.setBody("Validation failed")
End if
return $result
Dado que el parámetro $4DSID contiene una OTP válida correspondiente a la sesión original, el objeto Session hace referencia a la sesión que creó la OTP
He aquí el resultado en un navegador:
LA FUNCIÓN restore() EN EL OBJETO SESSION
Normalmente, se aplica un mecanismo de devolución de llamada cuando interviene un sistema de terceros. El principio es el siguiente
- enviar una solicitud al sistema de terceros y pasar una URL de devolución de llamada
- después de procesar la solicitud, el sistema de terceros llama a la URL de devolución de llamada
A veces, los sistemas de terceros no permiten que las URL de devolución de llamada contengan parámetros personalizados como $4DSID.
Sin embargo, permiten que se envíe información del cliente(por ejemplo, un estado), y el sistema de terceros devuelve esta información a la persona que llama. Esta es una forma de ser llamado de vuelta con una sesión web 4D OTP.
Consulte la documentación de la API del sistema de terceros para encontrar el nombre del parámetro en cuestión. El ejemplo siguiente utilizará el parámetro state.
Una función restore() está disponible en el objeto Session y permite recuperar la sesión correspondiente a un OTP dado.
En el ejemplo siguiente, la OTP se coloca en el parámetro de estado reservado en lugar de añadirse en la URL como parámetro $4DSID .
ejemplo
En una aplicación web 4D, un empleado de almacén selecciona productos para hacer un inventario y los envía a un sistema externo para su registro. Aquí se llama a la función sendProducts():
exposed Function sendProducts($chosenProducts : cs.ProductsSelection) : Text
var $token; $callBackURL; $callExternalAppURL; $result : Text
var $request : Object
//The chosen products are put in the session
Use (Session.storage)
Session.storage.info:=New shared object("inventoryStatus"; "Calling registring app")
Session.storage.chosenProducts:=$chosenProducts
End use
// $token is C318C81651F84F238EE72C14B46A45C3 (example)
$token:=Session.createOTP()
//Build the callback URL - Put the OTP in the state parameter
$callBackURL:="https://my4DApp/callBack?state="+$token
// Call the external registring system - Put the callback URL in the redirect parameter
$callExternalAppURL:="https://acme.com/callRegistringApp?redirect="+$callBackURL
$requestObj:={method: HTTP POST method}
$request:=4D.HTTPRequest.new($callExternalAppURL; $requestObj).wait()
// The external registring system made the call back. This call back retrieved and updated the Session
// So now the inventoryStatus attribute is up to date
If (Position("Products registered"; Session.storage.info.inventoryStatus)#0)
$result:=Session.storage.info.inventoryStatus
Else
$result:="Registering failed"
End if
return $result
Los productos elegidos se introducen en la sesión, y se genera un OTP.
Se llama al sistema externo. El parámetro de redirección indica la URL de devolución de llamada. Esta URL contiene el parámetro de estado, que es la OTP de la sesión.
En el ejemplo anterior, la URL del sistema de terceros es:
https://acme.com/callRegistringApp?redirect=https://my4DApp/callBack?state=C318C81651F84F238EE72C14B46A45C3
El prefijo URL /callBack es manejado por los HTTP request handlers (archivo HTTPHandlers.json) en la aplicación web 4D.
[
{
"class": "RequestHandler",
"method": "handleCallBack",
"regexPattern": "/callBack",
"verbs": "post"
}
]
Aquí está la función handleCallback() del singleton RequestHandler:
Function handleCallBack($request : 4D.IncomingMessage)
//Get the state parameter in the URL
$otp:=$request.urlQuery.state
//Restore the session thanks to the OTP
$restore:=Session.restore($otp)
//Restoring the session is successful
If ($restore=True)
//Get the body of the request (information sent by the third party system) - It contains "Products registered"
$text:=$request.getText()
//Update the session with the registring result
If ($text#Null)
Use (Session.storage.info)
Session.storage.info.inventoryStatus:=$text
If (Session.storage.chosenProducts#Null)
Session.storage.info.inventoryStatus+=" total price: "+String(Session.storage.chosenProducts.sum("price"))
End if
End use
End if
End if
Sobre el consumo de la licencia 4D Client
Sólo la sesión original (que genera el OTP) consume una licencia 4D Client. Restaurar una sesión (por ejemplo con un enlace de correo electrónico de validación) no consume ninguna licencia 4D Client adicional.
Descargue el HDI adjunto para ejecutar estos ejemplos en vivo y consulte la documentación para saber más.