Autenticación de Usuario en Web.py con SQLite

En este pequeño How-to realizaremos un pequeño aplicativo que nos permita tener una idea clara de cómo funcionan las sesiones y lo importante que son para nuestros App’s.

Un sistema de autenticación de usuario se compone de unas pocas partes. Adición de usuarios, logueo de usuarios, cierre de la sesión y comprobar si los usuarios están conectados.

Creamos nuestra bases de datos en SQLite:

$ sqlite3 users.db

sqlite> .tables
users
sqlite> insert into users values ('jolth', '123456');
sqlite> select * from users;
jolth|123456
sqlite> 
sqlite> .quit

Creamos nuestro sistema de Plantillas:

$ mkdir templates
$ vim templates/logeo.html
  1 $def with (form, msg=None)
  2 
  3 <form method="post">
  4     $if not form.valid: <p>Intenta de Nuevo...</p>
  5     $:form.render()
  6     <input type="submit" />
  7 </form>
  8 <p style="color:red;">$msg</p>

Creamos nuestro Aplicativo:

$ vim app.py
  1 # -*- coding: utf-8 -*-
  2 import sys
  3 import sqlite3 as db
  4 import web
  5 
  6 web.config.debug = False
  7 
  8 urls = (
  9     "/", "loggin",
 10     "/results", "results"
 11 )
 12 
 13 template = web.template.render('./templates')
 14 
 15 app = web.application(urls, globals())
 16 
 17 # Administración de sesiones (de web.py)
 18 session = web.session.Session(
 19         app,
 20         web.session.DiskStore('sesiones'),
 21         {'count': 0, 'loggedin': False}
 22 )
 23 
 24 # Fromulario de Login:
 25 login = web.form.Form(
 26     web.form.Textbox('Username', web.form.notnull),
 27     web.form.Password('Password', web.form.notnull),
 28 )
 29 
 30 class loggin:
 31     def GET(self):
 32         l = login()
 33         return template.logeo(login)
 34 
 35     def POST(self):
 36         l = login()
 37 
 38         # Validamos los campos del formulario
 39         if not l.validates():
 40             # Si los campos no tiene datos, 
 41             # retornamos la plantilla 'logeo.html'.
 42             return template.logeo(login, 'Debe rellenar los campos')
 43         else:
 44             i = web.input()
 45 
 46             try:
 47                 # Conexión a SQLite 
 48                 conn = db.connect("users.db")
 49                 cur = conn.cursor()
 50                 # Realizamos el Query. 
 51                 check = cur.execute('select * from users where username=? and password=?', (i.Username, i.Password))
 52 
 53                 # check.fetchone() sera una tupla (u'jolth', u'123456') o None sino existe. 
 54                 if check.fetchone():
 55                     # Creamos la Sesion
 56                     session.loggedin = True
 57                     session.username = i.Username
 58                     raise web.seeother('/results')
 59                 else:
 60                     return template.logeo(login, 'Usuario y Contraseña invalidos. session %s' % session.loggedin)
 61             except db.Error, e:
 62                 print "Error %s:" % e.args[0]
 63                 sys.exit(1)
 64             finally:
 65                 cur.close()
 66                 conn.close()
 67 
 68 
 69 class results:
 70     def GET(self):
 71         return "Login Exitoso(%s) %s" % (session.loggedin, session.username)
 72 
 73 
 74 if __name__ == "__main__": app.run()

Ok, ejecutemos nuestro App:

$ python app.py

E ingresamos a la URL http://127.0.0.1:8080/.

Que tal si decoramos las URL de nuestro aplicativo y le agregamos la capacidad de verificar si nuestro usuario tiene una sesión abierta.

  1 # -*- coding: utf-8 -*-
  2 import sys
  3 import sqlite3 as db
  4 import web
  5 
  6 web.config.debug = False
  7 
  8 urls = (
  9     "/", "loggin",
 10     "/results", "results"
 11 )
 12 
 13 template = web.template.render('./templates')
 14 
 15 app = web.application(urls, globals())
 16 
 17 # Administración de sesiones (de web.py)
 18 session = web.session.Session(
 19         app,
 20         web.session.DiskStore('sesiones'),
 21         {'count': 0, 'loggedin': False}
 22 )
 23 
 24 # Fromulario de Login:
 25 login = web.form.Form(
 26     web.form.Textbox('Username', web.form.notnull),
 27     web.form.Password('Password', web.form.notnull),
 28 )
 29 
 30 # Decorador para verificar la conexión (session)
 31 # de los usuarios, para cada una de las URL (clases)
 32 def Sesion(url):
 33     def verificaSesion(*args, **kwargs):
 34         print "Verificando Session: %s" % session.loggedin
 35         if not session.loggedin:
 36             raise web.seeother('/')
 37         return url(*args, **kwargs) # Llamamos a la clases 
 38     return verificaSesion
 39 
 40 
 41 class loggin:
 42     def GET(self):
 43         l = login()
 44         return template.logeo(login)
 45 
 46     def POST(self):
 47         l = login()
 48 
 49         # Validamos los campos del formulario
 50         if not l.validates():
 51 
 52             # retornamos la plantilla 'logeo.html'.
 53             return template.logeo(login, 'Debe rellenar los campos')
 54         else:
 55             i = web.input()
 56 
 57             try:
 58                 # Conexión a SQLite 
 59                 conn = db.connect("users.db")
 60                 cur = conn.cursor()
 61                 # Realizamos el Query. 
 62                 check = cur.execute('select * from users where username=? and password=?', (i.Username, i.Password))
 63 
 64                 # check.fetchone() sera una tupla (u'jolth', u'123456') o None sino existe. 
 65                 if check.fetchone():
 66                     # Creamos la Sesion
 67                     session.loggedin = True
 68                     session.username = i.Username
 69                     raise web.seeother('/results')
 70                 else:
 71                     return template.logeo(login, 'Usuario y Contraseña invalidos. session %s' % session.loggedin)
 72             except db.Error, e:
 73                 print "Error %s:" % e.args[0]
 74                 sys.exit(1)
 75             finally:
 76                 cur.close()
 77                 conn.close()
 78 
 79 
 80 class results:
 81     @Sesion
 82     def GET(self):
 83         return "Login Exitoso(%s) %s" % (session.loggedin, session.username)
 84 
 85 
 86 if __name__ == "__main__": app.run()

Lo que estamos buscando es que, por ejemplo un usuario nuevo intente ingresar a http://127.0.0.1:8080/results y no tiene una sesión abierta (session.loggedin=False) sea redireccionado inmediatamante a la página de logeo.html.

Para verificar el funcionamiento, debes cerrar el navegador donde tienes la sesión abierta, borrar la cache y abrirlo de nuevo (o desde un navegador diferente “en el que no hayas validado la sesión”) e ingresar a http://127.0.0.1:8080/results.

Aunque para nuestro ejemplo no fue necesario. Recordá siempre darle la posibilidad al usuario de realizar el cierre de la sesión (un session.kill()) con un enlace a por ejemplo ‘Logout‘.

Autor: Jolth

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s