diff --git a/.gitignore b/.gitignore
index 3374e77..0544496 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
nanowsgi.wpu
+auth_files/*
+
diff --git a/controllers/demo/due.py b/controllers/demo/due.py
index 993fc44..7628023 100644
--- a/controllers/demo/due.py
+++ b/controllers/demo/due.py
@@ -1,13 +1,15 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
-from decorators import WSGITemplate # decoratore ( singleton )
+from decorators import WSGISimpleAuth, WSGITemplate # decoratore ( singleton )
+auth = WSGISimpleAuth()
wsgitmpl = WSGITemplate()
#
# esempio minimo di controller WSGI
#
+@auth.require()
@wsgitmpl.template( 'template1.tmpl' )
def application( environ, start_response ):
from pprint import pformat
@@ -16,4 +18,4 @@ def application( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
- return [ html, pformat( environ, width=132 ).replace('\n','
\n') ] # TODO: pformat..... ---> trasformarlo in un decoratore
+ return [ html, '
', '', pformat( environ, width=132 ), '
' ] # TODO: pformat..... ---> trasformarlo in un decoratore
diff --git a/controllers/secret.py b/controllers/secret.py
new file mode 100644
index 0000000..d558f78
--- /dev/null
+++ b/controllers/secret.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
+
+from decorators import WSGISimpleAuth # decoratore ( singleton )
+auth = WSGISimpleAuth()
+
+@auth.require()
+def application( environ, start_response ):
+ storage = environ['auth.storage']
+
+ start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
+
+ return [
+ "The secret code is:
",
+ "''keep calm and carry on''
"
+ "uuid:%s
" % environ['auth.uuid'],
+ ]
diff --git a/decorators.py b/decorators.py
index 13576a5..d7cccce 100644
--- a/decorators.py
+++ b/decorators.py
@@ -9,9 +9,17 @@ from template import render
from functools import partial
## WSGIAuth
+import threading
+import re
import Cookie
import hashlib
import hmac
+import os
+import random
+import time
+import cPickle
+
+
md5 = lambda x : hashlib.md5( x ).hexdigest()
sha1 = lambda key,value: hmac.new( key, value, hashlib.sha1 ).hexdigest()
@@ -87,7 +95,6 @@ class WSGIMySQL( object ):
self.__dict_cursor = MySQLdb.cursors.DictCursor
-
def __newconn( self, alias ):
import MySQLdb
@@ -141,25 +148,103 @@ class WSGIMySQL( object ):
class WSGISimpleAuth( object ):
__metaclass__ = Singleton
- def __init__( self, secret_key, login_url=None, forbidden_url=None ):
- self.__secret_key = secret_key
+ def __init__( self, timeout=900, auth_dir = 'auth_files', login_url=None, forbidden_url=None ):
+ import os
+ self.__authdir = os.path.normpath( os.path.join( os.path.split(__file__)[0], auth_dir ) )
+ self.__timeout = timeout
+ self._lock = threading.RLock()
+
+ def uuid( self ):
+ """Generate a unique session ID"""
+ return hashlib.sha256(
+ str(os.getpid())
+ + str(time())
+ + str(random.random())
+ ).hexdigest()
- def auth( self, permission='', group='', p_g_mode='AND', p_mode='OR', g_mode='OR' ):
+ def acquire_lock(self):
+ self._lock.acquire()
+
+ def release_lock(self):
+ self._lock.release()
+
+
+ def require( self, permission='', group='', p_g_mode='AND', p_mode='OR', g_mode='OR' ):
def real_decorator( wsgi_application ):
def wrapper( environ, start_response ):
- try:
- uuid = Cookie.SimpleCookie(environ["HTTP_COOKIE"])["uuid"].value
- except:
- uuid = None
-
- environ['auth.uuid'] = uuid
+ #--------------------------------------------------------------
def my_start_response( status, response_headers ):
+ #
+ # aggiunge il cookie all'header
+ #
cookie = Cookie.SimpleCookie()
cookie["uuid"] = uuid
- response_headers.append( ('Set-Cookie',cookie.OutputString()) )
+ response_headers.append( ('Set-Cookie',cookie.output()) )
+
+ #
+ # salva le informazioni legate al cookie
+ #
+ storage['epoch_write'] = time.time()
+
+ self.acquire_lock() ## LOCK
+
+ f = open( path, 'w' )
+ try:
+ cPickle.dump(storage, f)
+ finally:
+ f.close()
+
+ self.release_lock() ## RELEASE
+
+ #
+ # start response originale
+ #
start_response( status, response_headers );
+ #--------------------------------------------------------------
+ #
+ # recupera UUID dal cookie
+ #
+ try:
+ uuid = Cookie.SimpleCookie(environ["HTTP_COOKIE"])["uuid"].value
+ except:
+ uuid = self.uuid()
+
+ #
+ # utilizza lo UUID per recuperare le informazioni (locali) ad esso legate
+ #
+ path = os.path.join( self.__authdir, uuid )
+
+ self.acquire_lock() ## LOCK
+
+ f = open( path, 'r' )
+
+ try:
+ storage = cPickle.load( f )
+ except:
+ # UUID assente, crea una nuova struttura dati
+ storage = {
+ 'epoch_created': time.time(),
+ 'permissions': [],
+ 'groups': [],
+ }
+
+ f.close()
+
+ self.release_lock() ## RELEASE
+
+ storage['epoch_read'] = time.time()
+
+ #
+ # popola environ
+ #
+ environ['auth.uuid'] = uuid
+ environ['auth.storage'] = storage
+
+ #
+ # output dei contenuti generati
+ #
for item in wsgi_application( environ, my_start_response ):
yield item
@@ -168,4 +253,22 @@ class WSGISimpleAuth( object ):
return real_decorator
-# EOF
\ No newline at end of file
+# EOF
+
+"""
+{
+ uuid: jkfghkjgdhfgkjlsk,
+ permission=[],
+ groups=[],
+ timeout=3600
+}
+
+
+
+{
+ uuid: jkfghkjgdhfgkjlsk,
+ permission=[],
+ groups=[],
+ timeout=3600
+}
+"""
\ No newline at end of file
diff --git a/dispatch_wsgi.py b/dispatch_wsgi.py
index 0681f63..0367835 100755
--- a/dispatch_wsgi.py
+++ b/dispatch_wsgi.py
@@ -36,6 +36,11 @@ WSGIMySQL(
),
)
+#
+# inizializzazione sistema di autenticazione
+#
+from decorators import WSGIMySQL
+WSGIMySQL( authdir='authfiles' )
#
# importazione handler definiti esternamente
@@ -71,12 +76,10 @@ def fallback( environ, start_response ):
#
# definiamo gli handler per le url che vogliamo servire
#
-################################################################################ from test_mysql import simple_mysql
handlers = (
( r'/', index ),
( r'/hello', hello ),
- ############################################################################ ( r'/mysql', simple_mysql ),
)
diff --git a/static/index.html b/static/index.html
index f384eff..84e1ecd 100644
--- a/static/index.html
+++ b/static/index.html
@@ -12,6 +12,7 @@
test autorouting
test autorouting (longest path possible)
test sql access
+ test authenticated

diff --git a/views/template1.tmpl b/views/template1.tmpl
index ea35cdc..7e08cf7 100644
--- a/views/template1.tmpl
+++ b/views/template1.tmpl
@@ -3,11 +3,10 @@ il valore di v1 è {{= v1 }}
mentre il valore di v2 è {{= v2 }}
-questo è il risultato di un loop che genera 10 valori casuali:
+questo è il risultato di un loop che genera 10 valori interi casuali:
{{ import random }}
{{ for x in range( 10 ): }}
-
- {{= random.randint( 10, 100 ) }}
+
+ {{= random.randint( 10, 10000 ) }}
{{ pass }}
-