Webové aplikace se dnes staly nedílnou součástí našeho života a nabízejí praktické funkce, které šetří čas a zjednodušují každodenní úkoly. Například vytváření účtů na různých platformách je jednou z nejčastějších činností uživatelů na webových stránkách.
Očekávají, že tento druh procesu bude rychlý a dostupný – ať už jsou doma, dojíždějí do práce nebo odpočívají na pláži.
Za touto jednoduchostí se skrývá složitější realita. Tyto operace často vyžadují integraci se systémy třetích stran, například se službami pro ověřování e-mailů. To přináší problémy spojené se zabezpečením, kontinuitou uživatelského prostředí a ochranou před útoky typu man-in-the-middle.
Pro vývojáře znamená zajištění bezproblémového provozu správu interakcí mezi externími systémy a webovou relací 4D. To zahrnuje zachování kontextu uživatele – načtení dat, oprávnění a přesného kroku jeho cesty k dokončení procesu.
Zní to složitě? Nemusí být! Zjistěte, jak pomocí 4D 20R9 vytvořit robustní webové aplikace, které bezpečně a efektivně komunikují se systémy třetích stran.
Ve webových aplikacích často uživatelská zkušenost vyžaduje několik kroků, jako např:
Při manipulaci se skladovými zásobami produktů:
- provést výběr produktů
- odeslání výběru do externího evidenčního systému
- dostat se zpět na seznam produktů v aplikaci
nebo
při vytváření účtu na webových stránkách:
- zadejte e-mail + heslo pro vytvoření účtu
- ověření e-mailu kliknutím na odkaz obdržený v e-mailu pro dokončení vytvoření účtu.
Tyto kroky vyžadují přechod tam a zpět se systémy třetích stran. Webová relace 4D tedy musí být na serveru jednoznačně identifikována, aby ji bylo možné později načíst.
FUNKCE createOTP() NA OBJEKTU SESSION
Identifikátorem relace webu 4D je cookie relace („4DSID_AppName„). Výměna hodnoty tohoto souboru cookie na síti mezi webovou aplikací 4D a systémem třetí strany je nešikovným narušením bezpečnosti.
Aby se tomu zabránilo, lze v jakémkoli webovém procesu vygenerovat jednorázový přístupový kód(OTP) díky nové funkci createOTP(), která je k dispozici na objektu Session.
Tento OTP je spojen s touto relací a umožňuje načtení v přijatém požadavku, kterému není předán soubor cookie relace.
Tento OTP lze použít pouze jednou a může být spojen s délkou života.
příklad
var $token : Text
$token:=Session.createOTP()
Jak načíst webovou relaci díky OTP?
Webovou relaci lze načíst dvěma způsoby.
pomocí parametru $4DSID v adrese URL
Webová relace se načte automaticky, pokud přijatý požadavek obsahuje v parametru $4DSID platné OTP odpovídající relaci.
příklad
V tomto příkladu je v datové třídě Users vytvořen uživatelský účet pomocí funkce create().
Je přijat objekt $info s e-mailem + heslem. Je vytvořen nový uživatel a do relace jsou uloženy některé informace, zejména aktuální krok procesu vytváření uživatelského účtu(Čekání na ověřovací e-mail) a ID uživatele.
Je vygenerováno OTP odpovídající aktuální relaci. Nakonec je vrácena adresa URL s tímto OTP uvedeným v parametru $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
Poté je uživateli zaslána tato adresa URL jako odkaz v e-mailu. URL s prefixem /validateEmail je zpracováváno obsluhami požadavků HTTP (soubor HTTPHandlers.json).
[
{
"class": "RequestHandler",
"method": "validateEmail",
"regexPattern": "/validateEmail",
"verbs": "get"
}
]
Zde je uvedena funkce validateEmail() singletonu 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
Protože parametr $4DSID obsahuje platné OTP odpovídající původní relaci, objekt Session odkazuje na relaci, která vytvořila OTP
Zde je výsledek v prohlížeči:
FUNKCE restore() NA OBJEKTU SESSION
Obvykle se při zapojení systému třetí strany používá mechanismus zpětného volání. Princip je následující:
- odeslat požadavek systému třetí strany a předat URL zpětného volání.
- po zpracování požadavku systém třetí strany zavolá zpětnou adresu URL.
Někdy systémy třetích stran neumožňují, aby URL zpětného volání obsahovaly vlastní parametry, například $4DSID.
Umožňují však odeslat informace o klientovi(např. stav) a systém třetí strany tyto informace vrátí volajícímu. Jedná se o způsob, jak být volán zpět pomocí OTP webové relace 4D.
Název příslušného parametru zjistíte v dokumentaci API systému třetí strany. V níže uvedeném příkladu bude použit parametr state (stav).
Na objektu Session je k dispozici funkce restore(), která umožňuje načíst relaci odpovídající danému OTP.
V níže uvedeném příkladu je OTP vloženo do vyhrazeného parametru state, místo aby bylo přidáno do adresy URL jako parametr $4DSID .
příklad
Ve webové aplikaci 4D vybírá zaměstnanec skladu výrobky pro provedení inventury a odesílá je do externího systému k zaevidování. Zde je volána funkce 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
Vybrané výrobky jsou vloženy do relace a je vygenerováno OTP.
Systém třetí strany je tzv. Parametr redirect označuje URL zpětného volání. Tato adresa URL obsahuje stavový parametr, kterým je OTP relace.
Ve výše uvedeném příkladu je adresa URL systému třetí strany následující:
https://acme.com/callRegistringApp?redirect=https://my4DApp/callBack?state=C318C81651F84F238EE72C14B46A45C3
Předponu URL /callBack zpracovávají obsluhy požadavků HTTP (soubor HTTPHandlers.json) ve webové aplikaci 4D.
[
{
"class": "RequestHandler",
"method": "handleCallBack",
"regexPattern": "/callBack",
"verbs": "post"
}
]
Zde je uvedena funkce handleCallback() singletonu 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
O spotřebě licence klienta 4D
Licenci 4D Client spotřebovává pouze původní relace (která generuje OTP). Obnovení relace (například pomocí ověřovacího e-mailového odkazu) nespotřebovává žádnou další licenci 4D Client.
Stáhněte si přiložené HDI, abyste mohli tyto příklady spustit naživo, a podívejte se do dokumentace, kde se dozvíte více.