Permalink
Browse files

updated httpauth and included demo for mongodb

  • Loading branch information...
1 parent 1c83d68 commit acb2fea9d8343fcccb533e1504358e718ef7afd6 @fiorix committed Feb 10, 2012
Showing with 124 additions and 133 deletions.
  1. +11 −0 demos/httpauth/README
  2. +113 −0 demos/httpauth/httpauthdemo_mongo.py
  3. +0 −6 demos/mongoauth/README
  4. +0 −36 demos/mongoauth/createuser.py
  5. +0 −91 demos/mongoauth/mongoauth.py
View
@@ -25,4 +25,15 @@ httpauthdemo_redis.py:
Then point your browser to http://localhost:8888 and authenticate as root/123.
+httpauthdemo_mongo.py:
+ Same as the above, but for the MongoDB database.
+ Make sure you have txredis installed, otherwise go grab it from GitHub:
+ https://github.com/fiorix/mongo-async-python-driver
+
+ Create a new user:
+ curl -D - -d "username=root&password=123" http://localhost:8888/createuser
+
+ Then point your browser to http://localhost:8888 and authenticate as root/123.
+
+
Have fun!
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+# coding: utf-8
+#
+# Copyright 2010 Alexandre Fiori
+# based on the original Tornado by Facebook
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import base64
+import functools
+import sys
+
+import cyclone.redis
+import cyclone.web
+
+from twisted.python import log
+from twisted.internet import defer, reactor
+
+try:
+ import txmongo
+except ImportError:
+ print("You need txmongo: "
+ "https://github.com/fiorix/mongo-async-python-driver")
+ sys.exit(1)
+
+
+class Application(cyclone.web.Application):
+ def __init__(self):
+ # Defaults to localhost:6379, dbid=0
+ mongodb = txmongo.lazyMongoConnectionPool()
+
+ handlers = [
+ (r"/", IndexHandler, dict(mongodb=mongodb)),
+ (r"/createuser", CreateUserHandler, dict(mongodb=mongodb)),
+ ]
+ cyclone.web.Application.__init__(self, handlers, debug=True)
+
+
+def HTTPBasic(method):
+ @defer.inlineCallbacks
+ @functools.wraps(method)
+ def wrapper(self, *args, **kwargs):
+ try:
+ auth_type, auth_data = self.request.headers["Authorization"].split()
+ assert auth_type == "Basic"
+ usr, pwd = base64.b64decode(auth_data).split(":", 1)
+ except:
+ raise cyclone.web.HTTPAuthenticationRequired
+
+ try:
+ # search for user under the "cyclonedb.users" collection
+ response = yield self.mongodb.cyclonedb.users.find_one(
+ {"usr":usr, "pwd":pwd}, fields=["usr"])
+ mongo_usr = response.get("usr")
+ except Exception, e:
+ log.msg("MongoDB failed to find(): %s" % str(e))
+ raise cyclone.web.HTTPError(503) # Service Unavailable
+
+ if usr != mongo_usr:
+ raise cyclone.web.HTTPAuthenticationRequired
+ else:
+ self._current_user = usr
+ defer.returnValue(method(self, *args, **kwargs))
+ return wrapper
+
+
+class IndexHandler(cyclone.web.RequestHandler):
+ def initialize(self, mongodb):
+ self.mongodb = mongodb
+
+ @HTTPBasic
+ def get(self):
+ self.write("Hi, %s." % self._current_user)
+
+
+class CreateUserHandler(cyclone.web.RequestHandler):
+ def initialize(self, mongodb):
+ self.mongodb = mongodb
+
+ @defer.inlineCallbacks
+ def post(self):
+ usr = self.get_argument("username")
+ pwd = self.get_argument("password")
+
+ try:
+ # create user under the "cyclonedb.users" collection
+ ObjId = yield self.mongodb.cyclonedb.users.update(
+ {"usr":usr}, {"usr":usr, "pwd":pwd}, upsert=True, safe=True)
+ except Exception, e:
+ log.msg("MongoDB failed to upsert(): %s" % str(e))
+ raise cyclone.web.HTTPError(503) # Service Unavailable
+
+ self.write("User created. ObjId=%s\r\n" % ObjId)
+
+
+def main():
+ log.startLogging(sys.stdout)
+ reactor.listenTCP(8888, Application(), interface="127.0.0.1")
+ reactor.run()
+
+
+if __name__ == "__main__":
+ main()
View
@@ -1,6 +0,0 @@
-User authentication using MongoDB
-http://www.mongodb.org
-
-Before using this example you need to install txmongo.
-git clone http://github.com/fiorix/mongo-async-python-driver.git
-cd mongo-async-python-driver ; python setup.py install
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-#
-# Copyright 2010 Alexandre Fiori
-# based on the original Tornado by Facebook
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import hashlib
-import txmongo
-from twisted.internet import defer, reactor
-
-@defer.inlineCallbacks
-def main():
- mongo = yield txmongo.MongoConnection()
-
- admin = yield mongo.mydb.users.find_one({"u":"cyclone"})
- if admin:
- print "user 'cyclone' with password 'cyclone' already exists: %s" % admin["_id"]
- else:
- objid = yield mongo.mydb.users.insert({"u":"cyclone", "p":hashlib.md5("cyclone").hexdigest()}, safe=True)
- print "user 'cyclone' with password 'cyclone' has been created: %s" % objid
-
-if __name__ == "__main__":
- main().addCallback(lambda ign: reactor.stop())
- reactor.run()
@@ -1,91 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-#
-# Copyright 2010 Alexandre Fiori
-# based on the original Tornado by Facebook
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import sys
-import hashlib
-import txmongo
-import cyclone.web
-from twisted.python import log
-from twisted.internet import defer, reactor
-
-class BaseHandler(cyclone.web.RequestHandler):
- def get_current_user(self):
- return self.get_secure_cookie("user")
-
-class MainHandler(BaseHandler):
- @cyclone.web.authenticated
- def get(self):
- self.write('great! <a href="/auth/logout">logout</a>')
-
-class LoginHandler(BaseHandler):
- def get(self):
- err = self.get_argument("e", None)
- self.finish("""
- <html><body><form action="/auth/login" method="post">
- username: <input type="text" name="u"><br>
- password: <input type="password" name="p"><br>
- <input type="submit" value="sign in"><br>
- %s
- </body></html>
- """ % (err == "invalid" and "invalid username or password" or ""))
-
- @defer.inlineCallbacks
- def post(self):
- u, p = self.get_argument("u"), self.get_argument("p")
-
- password = hashlib.md5(p).hexdigest()
- try:
- user = yield self.settings.mongo.mydb.users.find_one({"u":u, "p":password}, fields=["u"])
- except Exception, e:
- log.err("mongo can't find_one({u:%s, p:%s}): %s" % (u, password, e))
- raise cyclone.web.HTTPError(503)
-
- if user:
- user["_id"] = str(user["_id"])
- self.set_secure_cookie("user", cyclone.escape.json_encode(user))
- self.redirect("/")
- else:
- self.redirect("/auth/login?e=invalid")
-
-class LogoutHandler(BaseHandler):
- @cyclone.web.authenticated
- def get(self):
- self.clear_cookie("user")
- self.redirect("/")
-
-class Application(cyclone.web.Application):
- def __init__(self):
- handlers = [
- (r"/", MainHandler),
- (r"/auth/login", LoginHandler),
- (r"/auth/logout", LogoutHandler),
- ]
- settings = dict(
- login_url="/auth/login",
- cookie_secret="32oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
- mongo=txmongo.lazyMongoConnectionPool(),
- )
- cyclone.web.Application.__init__(self, handlers, **settings)
-
-def main(port):
- reactor.listenTCP(port, Application())
- reactor.run()
-
-if __name__ == '__main__':
- log.startLogging(sys.stdout)
- main(8888)

0 comments on commit acb2fea

Please sign in to comment.