Browse Source

persistenza su file del dizionario associato al cookie

auth
Andrea Papotti 13 years ago
parent
commit
3e5d83ba62
7 changed files with 147 additions and 20 deletions
  1. +2
    -0
      .gitignore
  2. +4
    -2
      controllers/demo/due.py
  3. +17
    -0
      controllers/secret.py
  4. +115
    -12
      decorators.py
  5. +5
    -2
      dispatch_wsgi.py
  6. +1
    -0
      static/index.html
  7. +3
    -4
      views/template1.tmpl

+ 2
- 0
.gitignore View File

@@ -1,2 +1,4 @@
nanowsgi.wpu
auth_files/*



+ 4
- 2
controllers/demo/due.py View File

@@ -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','<br>\n') ] # TODO: pformat..... ---> trasformarlo in un decoratore
return [ html, '<br><br><hr><br>', '<pre>', pformat( environ, width=132 ), '</pre>' ] # TODO: pformat..... ---> trasformarlo in un decoratore

+ 17
- 0
controllers/secret.py View File

@@ -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 [
"<h1>The secret code is:</h1>",
"<h6>''keep calm and carry on''</h6>"
"<h5>uuid:%s</h5>" % environ['auth.uuid'],
]

+ 115
- 12
decorators.py View File

@@ -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
# EOF

"""
{
uuid: jkfghkjgdhfgkjlsk,
permission=[],
groups=[],
timeout=3600
}



{
uuid: jkfghkjgdhfgkjlsk,
permission=[],
groups=[],
timeout=3600
}
"""

+ 5
- 2
dispatch_wsgi.py View File

@@ -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 ),
)




+ 1
- 0
static/index.html View File

@@ -12,6 +12,7 @@
<li><a href="/demo">test autorouting</a></li>
<li><a href="/demo/due">test autorouting (longest path possible)</a></li>
<li><a href="/demo/sql">test sql access</a></li>
<li><a href="/secret">test authenticated</a></li>
</ul>
<div style="position:fixed; bottom:0; left:10px;">
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_US"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/88x31.png" /></a>


+ 3
- 4
views/template1.tmpl View File

@@ -3,11 +3,10 @@ il valore di v1 è {{= v1 }}
<br>
mentre il valore di v2 è {{= v2 }}
<br>
questo è il risultato di un loop che genera 10 valori casuali:<br>
questo è il risultato di un loop che genera 10 valori interi casuali:<br>
{{ import random }}
{{ for x in range( 10 ): }}
<div style='background-color:{{ = random.choice( ('#fcc','yellow','#ccc','cyan',) ) }};'>
{{= random.randint( 10, 100 ) }}
<div style='background-color:#{{ = random.choice('89abcdef')*3 }};'>
{{= random.randint( 10, 10000 ) }}
</div>
{{ pass }}


Loading…
Cancel
Save