Conecte suas aplicações Web a sistemas de terceiros

Atualmente, as aplicações Web tornaram-se parte integrante das nossas vidas, oferecendo funcionalidades convenientes que poupam tempo e simplificam as tarefas diárias. Por exemplo, a criação de contas em várias plataformas é uma das ações mais frequentes dos utilizadores nos sítios Web.

Os usuários esperam que este tipo de processo seja rápido e acessível, quer estejam em casa, a caminho de casa ou a relaxar na praia.

Por detrás desta simplicidade esconde-se uma realidade mais complexa. Estas operações requerem frequentemente a integração com sistemas de terceiros, tais como serviços de verificação de correio eletrônico. Isto introduz desafios relacionados com a segurança, a continuidade da experiência do utilizador e a proteção contra os ataques do tipo man-in-the-middle.

Para os desenvolvedores, garantir uma experiência suave significa gerenciar interações entre sistemas externos e a sessão web 4D. Isso envolve manter o contexto do usuário – recuperando dados, privilégios, e o passo exato de sua jornada para completar o processo.

Parece complicado? Não tem que ser! Descubra como construir aplicações web robustas que se comunicam de forma segura e eficiente com sistemas de terceiros com 4D 20R9.

HDI_Session_Token

Muitas vezes, em aplicações web, a experiência do usuário requer vários passos como:

Ao lidar com inventários de produtos num armazém:

  • fazer uma seleção de produtos
  • enviar a seleção para um sistema de registo externo
  • voltar à lista de produtos na aplicação

ou

Ao criar uma conta num sítio Web:

  • introduzir o e-mail e a palavra-passe para criar a conta
  • validar o e-mail clicando numa ligação recebida num e-mail para finalizar a criação da conta

     

    Esses passos requerem ir e voltar com sistemas de terceiros. Assim, uma sessão web 4D deve ser identificada de forma única no servidor para ser recuperada mais tarde.

     

    A FUNÇÃO createOTP() NO OBJETO SESSION

    O identificador de uma sessão web 4D é o cookie de sessão (“4DSID_AppName“). Trocar esse valor de cookie na rede entre uma aplicação web 4D e um sistema de terceiros é uma quebra de segurança desajeitada.

    Para evitar isso, em qualquer processo web, um One-Time-Passcode(OTP) pode ser gerado graças à nova função createOTP() disponível no objeto Session.

    Este OTP está ligado a esta sessão e permite a sua recuperação num pedido recebido, ao qual não é atribuído o cookie de sessão.

    Este OTP só pode ser utilizado uma vez e pode ser associado a uma duração de vida.

    exemplo

    var $token : Text
    
    $token:=Session.createOTP()

    Como é que recupero uma sessão Web graças à OTP?

    A sessão Web pode ser recuperada de duas formas.

     

    o parâmetro $4DSID num URL

    A sessão Web será recuperada automaticamente se o pedido recebido contiver no parâmetro $4DSID uma OTP válida correspondente à sessão.

    exemplo

    Neste exemplo, é criada uma conta de utilizador na classe de dados Users com a função create().

    É recebido um objeto $info com o email + palavra-passe. É criado um novo utilizador e algumas informações são armazenadas na sessão, especialmente o passo atual do processo de criação da conta de utilizador(À espera do e-mail de validação) e o ID do utilizador.

    É gerada uma OTP correspondente à sessão atual. Finalmente, é devolvido um URL com este OTP fornecido no parâmetro $4DSID.

    // Na dataclass Users
    Function create($info : Object) : Text
    	
    var $user : cs.UsersEntity
    var $status : Object
    var $token : Text
    	
    //Uma nova entidade da dataclasse Users é criada
    $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

    Posteriormente, esta URL é enviada ao utilizador como um link numa mensagem de correio eletrônico. O prefixo de URL /validateEmail é tratado pelos manipuladores de pedidos HTTP (arquivo HTTPHandlers.json).

    [
      {
        "class": "RequestHandler",
        "method": "validateEmail",
        "regexPattern": "/validateEmail",
        "verbs": "get"
      }
    ]

    Aqui está a função validateEmail() do RequestHandler singleton.

    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 
            // Recupera a sessão com o OTP inválido
    	$result.setBody("Validation failed")
    End if 
    	
    return $result

    Como o parâmetro $4DSID contém uma OTP válida correspondente à sessão original, o objeto Session refere-se à sessão que criou a OTP

    Aqui está o resultado num browser:

    A FUNÇÃO restore() NO OBJECTO SESSION

    Normalmente, é aplicado um mecanismo de retorno de chamada quando estiver envolvido um sistema de terceiros. O princípio é o seguinte:

    • enviar um pedido ao sistema de terceiros e passar uma URL de retorno de chamada
    • depois de processar o pedido, o sistema externo chama a URL de retorno de chamada

     

    Por vezes, os sistemas de terceiros não permitem que as URL de retorno de chamada contenham parâmetros personalizados como $4DSID.

    No entanto, permitem que as informações do cliente (por exemplo, um estado) sejam enviadas e o sistema de terceiros devolve essas informações ao chamador. Esta é uma maneira de ser chamado de volta com uma sessão web 4D OTP.

    Verifique a documentação da API do sistema de terceiros para encontrar o nome do parâmetro em questão. O exemplo abaixo usará o parâmetro state.

    Uma função restore() está disponível no objeto Session e permite a recuperação da sessão correspondente a uma dada OTP.

    No exemplo abaixo, a OTP é colocada no parâmetro reservado state em vez de ser adicionada na URL como um parâmetro $4DSID .

    exemplo

    Em uma aplicação web 4D, um empregado de armazém seleciona produtos para fazer um inventário e os envia a um sistema externo para registro. Aqui está a função sendProducts() chamada:

    exposed Function sendProducts($chosenProducts : cs.ProductsSelection) : Text
    	
    var $token; $callBackURL; $callExternalAppURL; $result : Text
    var $request : Object
    	
    //Os produtos escolhidos são colocados na sessão
    Use (Session.storage)
    	Session.storage.info:=New shared object("inventoryStatus"; "Calling registring app")
    	Session.storage.chosenProducts:=$chosenProducts
    End use 
    	
    // $token é C318C81651F84F238EE72C14B46A45C3 (exemplo)
    $token:=Session.createOTP()
    	
    //Construa a URL de callback - Colocar a OTP no parâmetro state
    $callBackURL:="https://my4DApp/callBack?state="+$token
    	
    // Chama o sistema de registro externo - põe a URL de callback no parâmetro redirect
    $callExternalAppURL:="https://acme.com/callRegistringApp?redirect="+$callBackURL
    $requestObj:={method: HTTP POST method}
    $request:=4D.HTTPRequest.new($callExternalAppURL; $requestObj).wait()
    	
    // O sistema de registro externo fez a callback. Esta call back recupera e atualiza a Sessão
    // Agora o atributo inventoryStatus está atualizado
    If (Position("Products registered"; Session.storage.info.inventoryStatus)#0)
    	$result:=Session.storage.info.inventoryStatus
    Else 
    	$result:="Registering failed"
    End if 
    	
    return $result

    Os produtos escolhidos são colocados na sessão, e um OTP é gerado.

    O sistema de terceiros é chamado. O parâmetro de redirecionamento indica o URL de retorno de chamada. Esta URL contém o parâmetro de estado, que é a OTP da sessão.

    No exemplo acima, a URL do sistema de terceiros é:

    https://acme.com/callRegistringApp?redirect=https://my4DApp/callBack?state=C318C81651F84F238EE72C14B46A45C3

    O prefixo de URL /callBack é tratado pelos manipuladores de pedido HTTP (arquivo HTTPHandlers.json) na aplicação web 4D.

    [
      {
        "class": "RequestHandler",
        "method": "handleCallBack",
        "regexPattern": "/callBack",
        "verbs": "post"
      }
    ]

    Aqui está a função handleCallback() do RequestHandler singleton:

    Function handleCallBack($request : 4D.IncomingMessage)
    	
    //Obtém o parâmetro state na URL
    $otp:=$request.urlQuery.state
    	
    //Restaura a sessão graças ao OTP
    $restore:=Session.restore($otp)
    	
    //Restauração bem-sucedida da sessão
    If ($restore=True)
    	//Obtém o corpo da petição (informação enviada pelo sistema da terceira parte) - Contém "Products registered"
    	$text:=$request.getText()
    		
    	//Atualiza a sessão com os resultados registrados
    	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 o consumo de licença do Cliente 4D

    Apenas a sessão original (que gera o OTP) consome uma licença 4D Client. Restaurar uma sessão (por exemplo, com um link de email de validação) não consome nenhuma licença 4D Client adicional.

    Descarregue o HDI anexado para executar esses exemplos ao vivo e verifique a documentação para aprender mais.

    Avatar
    • Proprietário do produto - Marie-Sophie Landrieu -Yvert entrou ao time 4D Product como Proprietária do Produto em 2017. Como tal, está a cargo de escrever as histórias dos usuários e depois traduzi-las em especificações funcionais. Seu papel também é garantir que a implementação da funcionalidade entregue cumpra com as necessidades do cliente. Marie-sophie se formou na Escola de Engenharia de ESIGELEC e começou sua carreira como engenheira da IBM em 1995. Participou em vários projetos (de manutenção e criação) e trabalhou como desenvolvedora de Cobol. Depois trabalhou como designer de UML e desenvolvedora de Java. Suas principais funções foram analisar e redigir requisitos funcionais, coordenar os times de negócio e de desenvolvimento.