This repository has been archived by the owner on Oct 12, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
/
NewAuth
130 lines (125 loc) · 5.56 KB
/
NewAuth
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
It's a lot less complex than Carlos's AuthenticationFramework, and is a lot like CSAuthenticate while providing more flexibility.
{{{
#!python
from cherrypy.lib import aspect, httptools
from cherrypy import cpg
class NewAuth(aspect.Aspect):
"""
NewAuth is a more powerful authentication system for CherryPy which borrows from CSAuthenticate.
You'll probably want to override loginScreen, logoutScreen, loggedInScreen, and checkCredentials.
NewAuth is based on a system of roles. When a user logs in, they are assigned a list of roles they
belong to based on the credentials they give. Every object and method may have a roles attribute
which is a list of roles which are allowed to access a given resource.
The default implementation uses ugly forms which have customizable messages. It checks username
and password credentials via the loginMap dictionary, and if they match, assigns the user two roles:
"loggedIn" and their username.
"""
# all of these variables are for basic functionality which you should really override.
permissionMessage = "You do not have permission to access this page."
badCredentialsMessage = "Your credentials were invalid."
loggedInMessage = "You are now logged in."
loggedOutMessage = "You are now logged out."
loginMap = {"login":"password"}
def _before(self, methodName, method):
if not getattr(method, 'exposed', None):
return aspect.CONTINUE, None
if methodName in ["doLogin", "logout", "login"]:
return aspect.CONTINUE, None
userRoles = self.getUserRoles()
if hasattr(self, "roles"):
# first, check to see if he's got the controller credentials
requiredRoles = getattr(self, "roles")
ok = False
for role in userRoles:
if role in requiredRoles:
ok = True
break
if not ok:
return aspect.STOP, self.loginScreen(cpg.request.browserUrl, self.permissionMessage)
if hasattr(method, "roles"):
# now, check method credentials
requiredRoles = getattr(method, "roles")
ok = False
for role in userRoles:
if role in requiredRoles:
ok = True
break
if not ok:
return aspect.STOP, self.loginScreen(cpg.request.browserUrl, self.permissionMessage)
return aspect.CONTINUE, None
def getUserRoles(self):
return cpg.request.sessionMap.get("roles",[])
def loginScreen(self, fromPage="loggedIn", message=""):
"""
Override me. You *must* pass the fromPage variable on to doLogin, but
other than that you're free to choose what your form variable names are
(if you've overloaded checkCredentials). Don't change the arguments.
"""
return """
<html><body>
<form method="post" action="doLogin">
%s<br />
Login: <input type="text" name="login" size="10" /><br />
Password: <input type="password" name="password" size="10" /><br />
<input type="hidden" name="fromPage" value="%s" /><br />
<input type="submit" value="Login" />
</form>
</body></html>
""" % (message, fromPage)
def login(self):
return self.loginScreen()
login.exposed = True
def loggedInScreen(self):
"""
This is the default page you see if you've logged in. Feel free
to override it.
"""
return """
<html><body>%s</body></html>""" % self.loggedInMessage
def loggedIn(self):
return self.loggedInScreen()
loggedIn.exposed = True
def doLogin(self, fromPage, **kwargs):
roles = self.checkCredentials(**kwargs)
if len(roles) == 0:
return self.loginScreen(fromPage, self.badCredentialsMessage)
else:
cpg.request.sessionMap["roles"] = roles
httptools.redirect(fromPage)
return ""
doLogin.exposed = True
def logout(self):
cpg.request.sessionMap["roles"] = []
return self.logoutScreen()
logout.exposed = True
def logoutScreen(self):
"""
Override me to provide the screen which displays the logged out message.
"""
return """
<html><body>%s</body></html>""" % self.loggedOutMessage
def checkCredentials(self, login, password):
"""
Override me. Return a list of roles the user is now in. Return a list of length 0
if the user's credentials were invalid. This is passed the keyword args from doLogin, so you
can actually validate on any credentials you desire.
"""
desiredPassword = self.loginMap.get(login, False)
if desiredPassword and desiredPassword == password:
return ["loggedIn", login]
else:
return []
if __name__ == "__main__":
class Test(NewAuth):
roles = ["loggedIn"] # every exposed method in this object requires login
loginMap = {"login":"password","admin":"admin"}
def index(self):
return "index is protected by loggedIn"
index.exposed = True
def admin(self):
return "this can only be accessed by admin"
admin.exposed = True
admin.roles = ["admin"] # requires loggedIn _and_ admin
cpg.root = Test()
cpg.server.start(configDict={"port":8080,"sessionStorageType":"ram"})
}}}