Skip to content

Commit

Permalink
bcrypt and log_token added
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksandar Rodić committed Aug 30, 2012
1 parent d58a436 commit 15f46c8
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
*.pyc
8 changes: 4 additions & 4 deletions controllers/BaseHandler.py
@@ -1,7 +1,3 @@
import webapp2
import jinja2
import os

# Basic webapp2 handler with some useful methods # Basic webapp2 handler with some useful methods
# #
# render(template_name, template_vals={}) # render(template_name, template_vals={})
Expand All @@ -22,6 +18,10 @@
# get_params([param1, param2...]) - return [value1, value2...] # get_params([param1, param2...]) - return [value1, value2...]
# get_params_dict([param1, param2...]) - return {param1:value1, param2:value2} # get_params_dict([param1, param2...]) - return {param1:value1, param2:value2}


import webapp2
import jinja2
import os



head, tail = os.path.split(os.path.dirname(__file__)) head, tail = os.path.split(os.path.dirname(__file__))
template_dir = os.path.join(head, "templates") template_dir = os.path.join(head, "templates")
Expand Down
33 changes: 29 additions & 4 deletions controllers/authentication.py
Expand Up @@ -2,19 +2,44 @@
# #
# @Authentication.do decorator check # @Authentication.do decorator check
# if user is allowed to see a page # if user is allowed to see a page
#
#
# valid_login(username, password)
# valid_log_token(username, log_token)
# create_and_save_log_token(user)




from models.User import User from models.User import User
from externals.bcrypt import bcrypt as bc


class Authentication(object): class Authentication(object):


@staticmethod @staticmethod
def do(fn): def do(fn):
def wrapper(self, *args): def wrapper(self, *args):
username = self.request.cookies.get("username") username = self.request.cookies.get("username")
password = self.request.cookies.get("password") log_token = self.request.cookies.get("log_token")
if User.exist(username, password):
if Authentication.valid_log_token(username, log_token):
return fn(self, *args) return fn(self, *args)
else: else:
self.redirect("/forbidden") self.redirect("/forbidden")
return wrapper return wrapper

@staticmethod
def valid_login(username, password):
user = User.get_user(username)
if user and bc.hashpw(password, user.password) == user.password:
return Authentication.create_and_save_log_token(user)

@staticmethod
def valid_log_token(username, log_token):
user = User.get_user(username)
return user and bc.hashpw(log_token, user.log_token) == user.log_token

@staticmethod
def create_and_save_log_token(user):
log_token = bc.gensalt()
user.log_token = bc.hashpw(log_token, bc.gensalt())
user.put()
return log_token
10 changes: 6 additions & 4 deletions controllers/login.py
@@ -1,15 +1,17 @@
from BaseHandler import * from BaseHandler import *
from models.User import User from authentication import Authentication as aut
from externals.bcrypt import bcrypt as bc


class LoginPage(BaseHandler): class LoginPage(BaseHandler):
def get(self): def get(self):
self.render("login.html") self.render("login.html")


def post(self): def post(self):
params = self.get_params(["username", "password"]) params = self.get_params(["username", "password"])
if User.exist(*params): log_token = aut.valid_login(*params)
username, password = params if log_token:
self.set_cookies({"username":username, "password":password}) username, _ = params
self.set_cookies({"username":username, "log_token":log_token})
self.redirect("/") self.redirect("/")
else: else:
self.redirect("/login") self.redirect("/login")
2 changes: 1 addition & 1 deletion controllers/logout.py
Expand Up @@ -2,5 +2,5 @@


class LogoutPage(BaseHandler): class LogoutPage(BaseHandler):
def get(self): def get(self):
self.set_cookies({"username":"", "password":""}) self.set_cookies({"username":"", "log_token":""})
self.redirect("/") self.redirect("/")
9 changes: 9 additions & 0 deletions controllers/messages.py
@@ -0,0 +1,9 @@
from BaseHandler import *
from controllers.authentication import Authentication


class MessagePage(BaseHandler):

@Authentication.do
def get(self):
self.response.out.write("Hello World")
5 changes: 4 additions & 1 deletion controllers/signup.py
@@ -1,4 +1,6 @@
from BaseHandler import * from BaseHandler import *
from models.User import User
from authentication import Authentication as aut


class SignUpPage(BaseHandler): class SignUpPage(BaseHandler):


Expand All @@ -10,7 +12,8 @@ def post(self):
user = User.save(*params) user = User.save(*params)


if user: if user:
self.set_cookies({'username':user.username, 'password':user.password}) log_token = aut.create_and_save_log_token(user)
self.set_cookies({'username':user.username, 'log_token':log_token})
self.redirect("/") self.redirect("/")
else: else:
self.redirect("/signup") self.redirect("/signup")
Empty file added externals/__init__.py
Empty file.
1 change: 1 addition & 0 deletions externals/bcrypt
Submodule bcrypt added at 8fc098
4 changes: 3 additions & 1 deletion main.py
Expand Up @@ -4,12 +4,14 @@
from controllers.login import LoginPage from controllers.login import LoginPage
from controllers.logout import LogoutPage from controllers.logout import LogoutPage
from controllers.forbidden import Forbidden from controllers.forbidden import Forbidden
from controllers.messages import MessagePage


app = webapp2.WSGIApplication([ app = webapp2.WSGIApplication([
('/', HomePage), ('/', HomePage),
('/signup', SignUpPage), ('/signup', SignUpPage),
('/login', LoginPage), ('/login', LoginPage),
('/logout', LogoutPage), ('/logout', LogoutPage),
('/forbidden', Forbidden) ('/forbidden', Forbidden),
('/messages.*', MessagePage)
], debug=True) ], debug=True)


42 changes: 25 additions & 17 deletions models/User.py
@@ -1,5 +1,3 @@
from google.appengine.ext import db

# Simple user model that we can use # Simple user model that we can use
# in further development of pm part # in further development of pm part
# #
Expand All @@ -17,25 +15,38 @@
# SAVE # SAVE
# #
# save() - save and return user if valid() else False # save() - save and return user if valid() else False
#
#
# LOG TOKEN
#
# bcrypt.gensalt() is used for creating tokens
# tokens in database are hashed with bcrypt
# new token is generated with every new login




from google.appengine.ext import db
from externals.bcrypt import bcrypt as bc

class User(db.Model): class User(db.Model):
username = db.StringProperty(required=True) username = db.StringProperty(required=True)
password = db.StringProperty(required=True) password = db.StringProperty(required=True)
salt = db.StringProperty() email = db.StringProperty(required=True)
email = db.StringProperty(required=True) log_token = db.StringProperty(required=False)


@staticmethod
def get_user(username):
# shortcut for other classes that import User
return User.gql("WHERE username=:1", username).get()


@staticmethod @staticmethod
def valid_password(password): def valid_password(password):
n = len(password) return len(password) < 40
return n > 7 and n < 21


@staticmethod @staticmethod
def valid_username(username): def valid_username(username):
n = len(username) n = len(username)
users = User.gql("WHERE username=:1", username).get() users = User.get_user(username)
return users == None and n > 4 and n < 21 return not users and n > 4 and n < 21


@staticmethod @staticmethod
def valid_email(email): def valid_email(email):
Expand All @@ -52,12 +63,9 @@ def valid(username, email, password):
@staticmethod @staticmethod
def save(username, email, password): def save(username, email, password):
if User.valid(username, email, password): if User.valid(username, email, password):
user = User(username=username, password=password, email=email) password = bc.hashpw(password, bc.gensalt())
# call to create and save log token is in signup controller
user = User(username = username, password = password, email = email)
user.put() user.put()
return user return user
return False return False

@staticmethod
def exist(username, password):
user = User.gql("WHERE username=:1", username).get()
return user and user.password == password
1 change: 1 addition & 0 deletions templates/base.html
Expand Up @@ -8,6 +8,7 @@
<a href="/login">Login</a> <a href="/login">Login</a>
<a href="/signup">Sign up</a> <a href="/signup">Sign up</a>
<a href="/logout">Logout</a> <a href="/logout">Logout</a>
<a href="/messages">Messages</a>
</div> </div>
<div id="content"> <div id="content">
{% block content %} {% block content %}
Expand Down
1 change: 0 additions & 1 deletion templates/forbidden_resource.html
Expand Up @@ -2,5 +2,4 @@
{% block content %} {% block content %}
<h1>You are not authorized to see this page</h1> <h1>You are not authorized to see this page</h1>
<p>Go to <a href="/login">Login</a> or <a href="/signup">Sign up</a></p> <p>Go to <a href="/login">Login</a> or <a href="/signup">Sign up</a></p>
<a href="/">Home page</a>
{% endblock %} {% endblock %}

0 comments on commit 15f46c8

Please sign in to comment.