Autenticación de Usuarios con la base de datos PostgreSQL

Problema

Usted quiere un sistema para autentificar a los usuarios, con una base de datos PostgreSQL.

Solucion

Un sistema de autenticación de usuario puede tener una gran cantidad de funciones. Para este ejemplo, sólo se va a gestionar el proceso de autenticación, a través de una base de datos PostgreSQL.

Lo Necesario

web.py para todas las funciones web y hashlib para almacenar las contraseñas de forma segura.

  1 # -*- coding: utf-8 -*-
  2 import web
  3 import hashlib
  4

1. La base de datos

En primer lugar, se necesita una tabla para los usuarios. Este esquema es muy simple, pero es suficiente para un montón de proyectos.

$ psql -d myweb
CREATE TABLE users (
  id serial NOT NULL,
  usuario varchar(80) NOT NULL UNIQUE,
  pass char(40) NOT NULL,
  email varchar(100) NOT NULL,
  privilege integer NOT NULL DEFAULT 0,
  CONSTRAINT utilisateur_pkey PRIMARY KEY (id)
);

2. Las URL’s

Habrá 2 estados durante el inicio/cierre de la sesión:

Login – es la página de inicio de sesión
Reset – es la página de cierre de sesión.

sessions no funciona en modo depuración(debug) ya que interfieren con la recarga. ver session_with_reloader para más detalles.

  5 web.config.debug = False
  6 
  7 urls = (
  8           '/login', 'Login',
  9           '/reset', 'Reset',
 10        )    
 11 app = web.application(urls, locals())
 12 db = web.database(dbn='postgres', user='postgres', pw='qwerty', db='myweb')
 13 
 14 store = web.session.DiskStore('sessions')
 15 session = web.session.Session(app, store,
 16                               initializer={'login': 0, 'privilege': 0})
 17

3. logueado o no logueado?

Para gestionar el acceso de las personas que han iniciado sesión(logueado) o no, es muy fácil. Basta con definir logged y usarla en las clases login/reset:

 18 def logged():
 19     if session.login==1:
 20         return True
 21     else:
 22         return False
 23

4. Fácil gestión de los Privilegios

Puedo gestionar a mis usuarios en 4 categorías: admin+user+reader (logueados) y visitors (no logueados). El directorio de Plantillas es seleccionado acorde a los privilegios espacificados en la tabla “users“.

 24 def create_render(privilege):
 25     if logged():
 26         if privilege == 0:
 27             render = web.template.render('templates/reader')
 28         elif privilege == 1:
 29             render = web.template.render('templates/user')
 30         elif privilege == 2:
 31             render = web.template.render('templates/admin')
 32         else:
 33             render = web.template.render('templates/communs')
 34     else:
 35         render = web.template.render('templates/communs')
 36     return render
 37

5. Las clases Login y Reset

Ahora, vamos a divertirnos: Si ya está logueado, va a redirigir al archivo de plantilla login_double.html – Si no, a el login.html.

 38 class Login:
 39     def GET(self):
 40         if logged():
 41             render = create_render(session.privilege)
 42             return '%s' % render.login_double()
 43         else:
 44             render = create_render(session.privilege)
 45             return '%s' % render.login()
 46

Ok, ok. Ahora, para el POST(). De acuerdo con el fichero .html, recuperamos las variables de el formulario (ver el login.html), y lo comparamos con la fila “users.usuario” de nuestra tabla en PostgreSQL.
Por seguridad, no almacenar las contraseñas en la base de datos directamente, sino que almacenar el hash de la contraseña, lo que es una especie de línea decifrado, por lo que puede decir si las contraseñas de los usuarios coinciden, pero el atacante no podría entender que era la contraseña.
Si el login/pass están bien, se redirige a login_ok.html.
Si no, se redirige a login_error.html.

 47     def POST(self):
 48         name, passwd = web.input().name, web.input().passwd
 49         ident = db.select('users', where='usuario=$name', vars=locals())[0]
 50         try:
 51             if hashlib.sha1("sAlT754-"+passwd).hexdigest() == ident['pass']:
 52                 session.login = 1
 53                 session.privilege = ident['privilege']
 54                 render = create_render(session.privilege)
 55                 return render.login_ok()
 56             else:
 57                 session.login = 0
 58                 session.privilege = 0
 59                 render = create_render(session.privilege)
 60                 return render.login_error()
 61         except: 
 62             session.login = 0
 63             session.privilege = 0
 64             render = create_render(session.privilege)
 65             return render.login_error()
 66

Para la función Reset que mata la sesión y redirige a la plantilla logout.html.

 67 class Reset:
 68     def GET(self):
 69         session.login = 0
 70         session.kill()
 71         render = create_render(session.privilege)
 72         return render.logout()
 73

6. Ayudar a las plantillas HTML

Bueno, creo que nadie va a necesitar esto, pero, yo prefiero darles toda la información. El más importante es el login.html.

<form action="/login" method="POST">
    <table id="login">
        <tr>
            <td>User: </td>
            <td><input type="text" name="user"></td>
        </tr>
        <tr>
            <td>Password: </td>
            <td><input type="password" name="passwd"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="LOGIN"></td>
        </tr>
    </table>
</form>
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