Skip to content
Browse files

add basic authorization support

  • Loading branch information...
1 parent 1d044fe commit cbb6a436b3854774e4f07adbb226d23a68f794b6 @liut committed May 30, 2013
Showing with 75 additions and 18 deletions.
  1. +2 −0 config/imsto.ini
  2. +3 −1 imsto/_config.py
  3. +4 −1 imsto/_util.py
  4. +65 −15 imsto/handlers.py
  5. +1 −1 sbin/server_man.sh
View
2 config/imsto.ini
@@ -7,3 +7,5 @@ thumb_method = wand
max_file_size = 102400
support_size = 120,130,160
url_prefix = http://m.imsto.net/
+admin_name = liutao
+admin_pass =
View
4 imsto/_config.py
@@ -35,7 +35,9 @@ def __init__(self):
'url_prefix': 'http://m.imsto.net/',
'eggs_cache': '/opt/imsto/cache/eggs',
'max_file_size': '102400',
- 'support_size': '120,160,250,400'
+ 'support_size': '120,160,250,400',
+ 'admin_name': 'imsto',
+ 'admin_pass': '',
}
self.config = ConfigParser.SafeConfigParser(defaulting)
if os.environ.has_key('IMSTO_CONF_DIR'):
View
5 imsto/_util.py
@@ -11,7 +11,7 @@
from _wand import NewMagickWand,MagickReadImage,MagickToMime,\
MagickGetImageFormat,MagickGetImageWidth,MagickGetImageHeight,MagickGetImageCompressionQuality
-__all__ = ['check_dirs', 'save_file', 'thumbnail_wand', 'thumb_image', 'guess_mimetype', 'watermark_image']
+__all__ = ['check_dirs', 'save_file', 'thumbnail_wand', 'thumb_image', 'guess_mimetype', 'watermark_image', 'password_hash']
def check_dirs(filename):
dir_name = os.path.dirname(filename)
@@ -157,6 +157,9 @@ def watermark_image(filename, distname):
del im_w
return r
+def password_hash(username, password):
+ from hashlib import sha1
+ return sha1(':'.join([username.lower(), password])).hexdigest()
View
80 imsto/handlers.py
@@ -1,11 +1,11 @@
-import os
+import os,re
import json
from sys import exc_info
from traceback import format_tb
from imsto import *
-__all__ = ['ErrorHandle','ImageHandler','AdminHandler']
+__all__ = ['ErrorWrap','AuthWrap','AuthAdminHandle','ImageHandler','AdminHandler']
def abuilding(self, environ, start_response):
"""show abuilding"""
@@ -31,42 +31,89 @@ def get_path_info(environ):
#print 'path: %s (%s)' % (path, type(path))
return path
-class ErrorHandle(object):
+class ErrorWrap(object):
"""The middleware we use."""
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
"""Call the application can catch exceptions."""
appiter = None
- # just call the application and send the output back
- # unchanged but catch exceptions
try:
appiter = self.app(environ, start_response)
for item in appiter:
yield item
- # if an exception occours we get the exception information
- # and prepare a traceback we can render
except:
e_type, e_value, tb = exc_info()
traceback = ['Traceback (most recent call last):']
traceback += format_tb(tb)
traceback.append('%s: %s' % (e_type.__name__, e_value))
- # we might have not a stated response by now. try
- # to start one with the status code 500 or ignore an
- # raised exception if the application already started one.
try:
start_response('500 INTERNAL SERVER ERROR', [
('Content-Type', 'text/plain')])
except:
pass
yield '\n'.join(traceback)
- # wsgi applications might have a close function. If it exists
- # it *must* be called.
if hasattr(appiter, 'close'):
appiter.close()
+
+class AuthWrap(object):
+
+ def __init__(self, app):
+ self.app = app
+ self.section = 'imsto'
+ self.config = Config()
+
+ def __call__(self, environ, start_response):
+ self.section = environ.get('IMSTO_SECTION', 'imsto')
+ if not self.authorized(environ.get('HTTP_AUTHORIZATION')):
+ return self.auth_required(environ, start_response)
+ return self.app(environ, start_response)
+
+ def authorized(self, auth_header):
+ if not auth_header:
+ # If they didn't give a header, they better login...
+ return False
+ # .split(None, 1) means split in two parts on whitespace:
+ auth_type, encoded_info = auth_header.split(None, 1)
+ #print '{}, {}'.format(auth_type, encoded_info)
+ assert auth_type.lower() == 'basic'
+ unencoded_info = encoded_info.decode('base64')
+ username, password = unencoded_info.split(':', 1)
+ return self.check_password(username, password)
+
+ def check_password(self, username, password):
+ # Not very high security authentication...
+ admin_name = self.config.get('admin_name')
+ admin_pass = self.config.get('admin_pass')
+ #print 'input %s:%s' % (username, password)
+ if username != admin_name:
+ return False
+ if admin_pass == '':
+ print 'admin_pass is empty!'
+ return True
+
+ #hashed = password_hash(username, password)
+ #print '{} admin_pass\n{} hashed'.format(admin_pass, hashed)
+ return password_hash(username, password) == admin_pass
+
+ def auth_required(self, environ, start_response):
+ start_response('401 Authentication Required',
+ [('Content-type', 'text/html'),
+ ('WWW-Authenticate', 'Basic realm="imsto"')])
+ return ["""
+ <html>
+ <head><title>Authentication Required</title></head>
+ <body>
+ <h1>Authentication Required</h1>
+ If you can't get in, then stay out.
+ </body>
+ </html>"""]
+
+
+
def ImageHandler(environ, start_response):
"""main image url handler"""
SECTION = environ.get('IMSTO_SECTION', 'imsto')
@@ -105,12 +152,12 @@ def AdminHandler(environ, start_response):
path = get_path_info(environ)
man_regex = r'(env|Gallery|Stored)$'
- match = re.search(man_regex, path_info)
+ match = re.search(man_regex, path)
#print('match: {0}'.format(match))
if match is None:
return not_found(environ, start_response)
- action = match.groups()[1]
+ action, = match.groups()
if (action == 'Gallery'):
from cgi import FieldStorage
form = FieldStorage(environ=environ)
@@ -195,6 +242,8 @@ def StoredHandler(environ, start_response):
return [json.dumps([False, 'invalid operation'])]
+AuthAdminHandle = ErrorWrap(AuthWrap(AdminHandler))
+
# map urls to functions
default_urls = [
@@ -229,6 +278,7 @@ def application(environ, start_response):
httpd.serve_forever()
else:
- application = ErrorHandle(application)
+ application = ErrorWrap(application)
+
View
2 sbin/server_man.sh
@@ -11,7 +11,7 @@
### END INIT INFO
name="manage"
-uwsgi_module="app.managehandle"
+uwsgi_module="imsto.handlers:AuthAdminHandle"
uwsgi_socket="/tmp/imsto_man.sock"
prefix=/opt/imsto

0 comments on commit cbb6a43

Please sign in to comment.
Something went wrong with that request. Please try again.