Flutter
...
Authentication
Guía para obtener usuario actual con Parse en Flutter
13 min
obtener el usuario actual en la sesión introducción no sería agradable si el usuario tuviera que iniciar sesión cada vez que abre tu aplicación puedes evitar esto utilizando el objeto parseuser actual en caché siempre que uses cualquier método de registro o inicio de sesión, el usuario se almacena localmente puedes gestionar esta caché como una sesión y asumir automáticamente que el usuario ha iniciado sesión en esta guía, aprenderás cómo usar el plugin de flutter para parse server para obtener el usuario actual en la sesión utilizando la clase parseuser para tu aplicación flutter objetivo obtener el usuario actual en la sesión utilizando parse para una aplicación flutter requisitos previos para completar este tutorial, necesitarás flutter versión 2 2 x o posterior https //flutter dev/docs/get started/install android studio https //developer android com/studio o vs code instalado (con plugins dart y flutter) una aplicación flutter creada y conectada a back4app nota sigue el instalar parse sdk en el proyecto flutter para crear un proyecto flutter conectado a back4app completa la guía anterior para que puedas tener una mejor comprensión de la parseuser parseuser clase un dispositivo (no simulador) que ejecute android o ios entendiendo la aplicación obtener usuario actual para entender mejor el proceso de obtener el usuario actual en sesión, crearemos una aplicación para registrar, iniciar sesión y cerrar sesión de un usuario la aplicación es similar a la guía anterior, donde realizamos el registro, inicio de sesión y cierre de sesión como vamos a usar el mismo proyecto en las siguientes guías, puedes encontrar algunas funciones que aún no están disponibles no explicaremos el código de la aplicación flutter ya que el enfoque principal de esta guía es usar flutter con parse siguiendo los siguientes pasos, construirás una aplicación de inicio y cierre de sesión en la base de datos de back4app ¡comencemos! en los siguientes pasos, podrás construir una aplicación para obtener el usuario actual 1 crear la plantilla de la aplicación de inicio/cierre de sesión abre tu proyecto de flutter de la guía anterior flutter plugin for parse server ve al archivo main dart, limpia todo el código y reemplázalo con 1 import 'package\ flutter/material dart'; 2 import 'package\ parse server sdk flutter/parse server sdk dart'; 3 4 void main() async { 5 widgetsflutterbinding ensureinitialized(); 6 7 final keyapplicationid = 'your app id here'; 8 final keyclientkey = 'your client key here'; 9 final keyparseserverurl = 'https //parseapi back4app com'; 10 11 await parse() initialize(keyapplicationid, keyparseserverurl, 12 clientkey keyclientkey, 13 debug true); 14 15 runapp(myapp()); 16 } 17 18 class myapp extends statelesswidget { 19 future\<bool> hasuserlogged() async { 20 return future value(false); 21 } 22 23 @override 24 widget build(buildcontext context) { 25 return materialapp( 26 title 'flutter parse server', 27 theme themedata( 28 primaryswatch colors blue, 29 visualdensity visualdensity adaptiveplatformdensity, 30 ), 31 home futurebuilder\<bool>( 32 future hasuserlogged(), 33 builder (context, snapshot) { 34 switch (snapshot connectionstate) { 35 case connectionstate none 36 case connectionstate waiting 37 return scaffold( 38 body center( 39 child container( 40 width 100, 41 height 100, 42 child circularprogressindicator()), 43 ), 44 ); 45 default 46 if (snapshot hasdata && snapshot data!) { 47 return userpage(); 48 } else { 49 return loginpage(); 50 } 51 } 52 }), 53 ); 54 } 55 } 56 57 class loginpage extends statefulwidget { 58 @override 59 loginpagestate createstate() => loginpagestate(); 60 } 61 62 class loginpagestate extends state\<loginpage> { 63 final controllerusername = texteditingcontroller(); 64 final controllerpassword = texteditingcontroller(); 65 bool isloggedin = false; 66 67 @override 68 widget build(buildcontext context) { 69 return scaffold( 70 appbar appbar( 71 title const text('flutter parse server'), 72 ), 73 body center( 74 child singlechildscrollview( 75 padding const edgeinsets all(8), 76 child column( 77 crossaxisalignment crossaxisalignment stretch, 78 children \[ 79 container( 80 height 200, 81 child image network( 82 'https //blog back4app com/wp content/uploads/2017/11/logo b4a 1 768x175 1 png'), 83 ), 84 center( 85 child const text('flutter on back4app', 86 style 87 textstyle(fontsize 18, fontweight fontweight bold)), 88 ), 89 sizedbox( 90 height 16, 91 ), 92 textfield( 93 controller controllerusername, 94 enabled !isloggedin, 95 keyboardtype textinputtype text, 96 textcapitalization textcapitalization none, 97 autocorrect false, 98 decoration inputdecoration( 99 border outlineinputborder( 100 borderside borderside(color colors black)), 101 labeltext 'username'), 102 ), 103 sizedbox( 104 height 8, 105 ), 106 textfield( 107 controller controllerpassword, 108 enabled !isloggedin, 109 obscuretext true, 110 keyboardtype textinputtype text, 111 textcapitalization textcapitalization none, 112 autocorrect false, 113 decoration inputdecoration( 114 border outlineinputborder( 115 borderside borderside(color colors black)), 116 labeltext 'password'), 117 ), 118 sizedbox( 119 height 16, 120 ), 121 container( 122 height 50, 123 child elevatedbutton( 124 child const text('login'), 125 onpressed isloggedin ? null () => douserlogin(), 126 ), 127 ), 128 sizedbox( 129 height 16, 130 ), 131 container( 132 height 50, 133 child elevatedbutton( 134 child const text('sign up'), 135 onpressed () => navigatetosignup(), 136 ), 137 ), 138 sizedbox( 139 height 16, 140 ), 141 container( 142 height 50, 143 child elevatedbutton( 144 child const text('reset password'), 145 onpressed () => navigatetoresetpassword(), 146 ), 147 ) 148 ), 149 ), 150 ), 151 )); 152 } 153 154 void douserlogin() async { 155 final username = controllerusername text trim(); 156 final password = controllerpassword text trim(); 157 158 final user = parseuser(username, password, null); 159 160 var response = await user login(); 161 162 if (response success) { 163 navigatetouser(); 164 } else { 165 message showerror(context context, message response error! message); 166 } 167 } 168 169 void navigatetouser() { 170 navigator pushandremoveuntil( 171 context, 172 materialpageroute(builder (context) => userpage()), 173 (route\<dynamic> route) => false, 174 ); 175 } 176 177 void navigatetosignup() { 178 navigator push( 179 context, 180 materialpageroute(builder (context) => signuppage()), 181 ); 182 } 183 184 void navigatetoresetpassword() { 185 navigator push( 186 context, 187 materialpageroute(builder (context) => resetpasswordpage()), 188 ); 189 } 190 } 191 192 class signuppage extends statefulwidget { 193 @override 194 signuppagestate createstate() => signuppagestate(); 195 } 196 197 class signuppagestate extends state\<signuppage> { 198 final controllerusername = texteditingcontroller(); 199 final controllerpassword = texteditingcontroller(); 200 final controlleremail = texteditingcontroller(); 201 202 @override 203 widget build(buildcontext context) { 204 return scaffold( 205 appbar appbar( 206 title const text('flutter sign up'), 207 ), 208 body center( 209 child singlechildscrollview( 210 padding const edgeinsets all(8), 211 child column( 212 crossaxisalignment crossaxisalignment stretch, 213 children \[ 214 container( 215 height 200, 216 child image network( 217 'https //blog back4app com/wp content/uploads/2017/11/logo b4a 1 768x175 1 png'), 218 ), 219 center( 220 child const text('flutter on back4app', 221 style 222 textstyle(fontsize 18, fontweight fontweight bold)), 223 ), 224 sizedbox( 225 height 16, 226 ), 227 center( 228 child const text('user registration', 229 style textstyle(fontsize 16)), 230 ), 231 sizedbox( 232 height 16, 233 ), 234 textfield( 235 controller controllerusername, 236 keyboardtype textinputtype text, 237 textcapitalization textcapitalization none, 238 autocorrect false, 239 decoration inputdecoration( 240 border outlineinputborder( 241 borderside borderside(color colors black)), 242 labeltext 'username'), 243 ), 244 sizedbox( 245 height 8, 246 ), 247 textfield( 248 controller controlleremail, 249 keyboardtype textinputtype emailaddress, 250 textcapitalization textcapitalization none, 251 autocorrect false, 252 decoration inputdecoration( 253 border outlineinputborder( 254 borderside borderside(color colors black)), 255 labeltext 'e mail'), 256 ), 257 sizedbox( 258 height 8, 259 ), 260 textfield( 261 controller controllerpassword, 262 obscuretext true, 263 keyboardtype textinputtype text, 264 textcapitalization textcapitalization none, 265 autocorrect false, 266 decoration inputdecoration( 267 border outlineinputborder( 268 borderside borderside(color colors black)), 269 labeltext 'password'), 270 ), 271 sizedbox( 272 height 8, 273 ), 274 container( 275 height 50, 276 child elevatedbutton( 277 child const text('sign up'), 278 onpressed () => douserregistration(), 279 ), 280 ) 281 ], 282 ), 283 ), 284 )); 285 } 286 287 void douserregistration() async { 288 final username = controllerusername text trim(); 289 final email = controlleremail text trim(); 290 final password = controllerpassword text trim(); 291 292 final user = parseuser createuser(username, password, email); 293 294 var response = await user signup(); 295 296 if (response success) { 297 message showsuccess( 298 context context, 299 message 'user was successfully created!', 300 onpressed () async { 301 navigator pushandremoveuntil( 302 context, 303 materialpageroute(builder (context) => userpage()), 304 (route\<dynamic> route) => false, 305 ); 306 }); 307 } else { 308 message showerror(context context, message response error! message); 309 } 310 } 311 } 312 313 class userpage extends statelesswidget { 314 parseuser? currentuser; 315 316 future\<parseuser?> getuser() async { 317 } 318 319 @override 320 widget build(buildcontext context) { 321 void douserlogout() async { 322 var response = await currentuser! logout(); 323 if (response success) { 324 message showsuccess( 325 context context, 326 message 'user was successfully logout!', 327 onpressed () { 328 navigator pushandremoveuntil( 329 context, 330 materialpageroute(builder (context) => loginpage()), 331 (route\<dynamic> route) => false, 332 ); 333 }); 334 } else { 335 message showerror(context context, message response error! message); 336 } 337 } 338 339 return scaffold( 340 appbar appbar( 341 title text('user logged in current user'), 342 ), 343 body futurebuilder\<parseuser?>( 344 future getuser(), 345 builder (context, snapshot) { 346 switch (snapshot connectionstate) { 347 case connectionstate none 348 case connectionstate waiting 349 return center( 350 child container( 351 width 100, 352 height 100, 353 child circularprogressindicator()), 354 ); 355 default 356 return padding( 357 padding const edgeinsets all(8 0), 358 child column( 359 crossaxisalignment crossaxisalignment stretch, 360 mainaxisalignment mainaxisalignment center, 361 children \[ 362 center( 363 child text('hello, ${snapshot data! username}')), 364 sizedbox( 365 height 16, 366 ), 367 container( 368 height 50, 369 child elevatedbutton( 370 child const text('logout'), 371 onpressed () => douserlogout(), 372 ), 373 ), 374 ], 375 ), 376 ); 377 } 378 })); 379 } 380 } 381 382 class resetpasswordpage extends statefulwidget { 383 @override 384 resetpasswordpagestate createstate() => resetpasswordpagestate(); 385 } 386 387 class resetpasswordpagestate extends state\<resetpasswordpage> { 388 final controlleremail = texteditingcontroller(); 389 390 @override 391 widget build(buildcontext context) { 392 return scaffold( 393 appbar appbar( 394 title text('reset password'), 395 ), 396 body singlechildscrollview( 397 padding const edgeinsets all(8), 398 child column( 399 crossaxisalignment crossaxisalignment stretch, 400 children \[ 401 textfield( 402 controller controlleremail, 403 keyboardtype textinputtype emailaddress, 404 textcapitalization textcapitalization none, 405 autocorrect false, 406 decoration inputdecoration( 407 border outlineinputborder( 408 borderside borderside(color colors black)), 409 labeltext 'e mail'), 410 ), 411 sizedbox( 412 height 8, 413 ), 414 container( 415 height 50, 416 child elevatedbutton( 417 child const text('reset password'), 418 onpressed () => douserresetpassword(), 419 ), 420 ) 421 ], 422 ), 423 )); 424 } 425 426 void douserresetpassword() async {} 427 } 428 429 class message { 430 static void showsuccess( 431 {required buildcontext context, 432 required string message, 433 voidcallback? onpressed}) { 434 showdialog( 435 context context, 436 builder (buildcontext context) { 437 return alertdialog( 438 title const text("success!"), 439 content text(message), 440 actions \<widget>\[ 441 new elevatedbutton( 442 child const text("ok"), 443 onpressed () { 444 navigator of(context) pop(); 445 if (onpressed != null) { 446 onpressed(); 447 } 448 }, 449 ), 450 ], 451 ); 452 }, 453 ); 454 } 455 456 static void showerror( 457 {required buildcontext context, 458 required string message, 459 voidcallback? onpressed}) { 460 showdialog( 461 context context, 462 builder (buildcontext context) { 463 return alertdialog( 464 title const text("error!"), 465 content text(message), 466 actions \<widget>\[ 467 new elevatedbutton( 468 child const text("ok"), 469 onpressed () { 470 navigator of(context) pop(); 471 if (onpressed != null) { 472 onpressed(); 473 } 474 }, 475 ), 476 ], 477 ); 478 }, 479 ); 480 } 481 } 482 cuando debug debug el parámetro en la función parse() initialize parse() initialize es true true , permite mostrar las llamadas a la api de parse en la consola esta configuración puede ayudarte a depurar el código es prudente desactivar el debug en la versión de lanzamiento 2 conectar la plantilla al proyecto de back4app encuentra tu id de aplicación y las credenciales de client key navegando a tu panel de control de la aplicación en sitio web de back4app https //www back4app com/ actualiza tu código en main dart main dart con los valores de applicationid y clientkey de tu proyecto en back4app keyapplicationid = app id keyclientkey = client key ejecuta el proyecto, y la aplicación se cargará como se muestra en la imagen 3 código para obtener el usuario actual en la sesión la función de inicio de sesión o registro de usuario crea un sesión sesión objeto, que apunta al usuario usuario que ha iniciado sesión y almacena en tu almacenamiento local una sesión de usuario válida las llamadas a los métodos currentuser currentuser recuperarán con éxito tus parseuser parseuser datos y sessiontoken sessiontoken para el session session objeto busca la función hasuserlogged hasuserlogged en el archivo main dart main dart reemplaza el código dentro de hasuserlogged hasuserlogged con 1 parseuser? currentuser = await parseuser currentuser() as parseuser?; 2 if (currentuser == null) { 3 return false; 4 } 5 //checks whether the user's session token is valid 6 final parseresponse? parseresponse = 7 await parseuser getcurrentuserfromserver(currentuser sessiontoken!); 8 9 if (parseresponse? success == null || !parseresponse! success) { 10 //invalid session logout 11 await currentuser logout(); 12 return false; 13 } else { 14 return true; 15 } para construir esta función, sigue estos pasos llama a la parseuser currentuser() parseuser currentuser() función, que devolverá un parseuser parseuser objeto del almacenamiento local si parseuser parseuser es nulo, no tenemos ningún usuario con una sesión activa en la aplicación si parseuser parseuser no es nulo, tenemos un usuario con una sesión activa en nuestra aplicación la sesión del usuario necesita ser validada en el servidor de parse, ya que tiene una duración si el token no es válido, es necesario llamar a la función de cierre de sesión para limpiar la sesión actual y el usuario necesita iniciar sesión nuevamente la función completa debería verse así 1 future\<bool> hasuserlogged() async { 2 parseuser? currentuser = await parseuser currentuser() as parseuser?; 3 if (currentuser == null) { 4 return false; 5 } 6 //checks whether the user's session token is valid 7 final parseresponse? parseresponse = 8 await parseuser getcurrentuserfromserver(currentuser sessiontoken!); 9 10 if (parseresponse? success == null || !parseresponse! success) { 11 //invalid session logout 12 await currentuser logout(); 13 return false; 14 } else { 15 return true; 16 } 17 } busca la función getuser getuser en el archivo main dart main dart reemplaza el código dentro de getuser getuser con 1 currentuser = await parseuser currentuser() as parseuser?; 2 return currentuser; para construir esta función, sigue estos pasos llama a la parseuser currentuser() parseuser currentuser() función, que devolverá un parseuser parseuser objeto del almacenamiento local la función completa debería verse así 1 future\<parseuser> getuser() async { 2 currentuser = await parseuser currentuser() as parseuser?; 3 return currentuser; 4 } para probarlo, haz clic en el ejecutar ejecutar botón en android studio/vscode regístrate o inicia sesión y la siguiente pantalla mostrará el nombre de usuario del usuario conectado cierra la aplicación y vuelve a ejecutarla si se identifica una sesión de usuario válida, se mostrará la pantalla con el nombre de usuario ¡está hecho! al final de esta guía, puedes obtener el usuario actual en la sesión de tu aplicación utilizando las características principales de parse server a través de back4app!