alef13
11 Jan 2008, 7:07 PM
I wrote this simple authentication mechanism using FormPanel. There are examples of login and logout scripts written in python, but it lacks session management because it's out of the scope.
I assume that apache is configured properly and python extensions such as cgi and json are already installed.
Below is the first file, index.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="ext-2.0/resources/css/ext-all.css">
<style rel="stylesheet" type="text/css">
.panel-items{margin:10px;}
</style>
<script type="text/javascript" src="ext-2.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-2.0/ext-all.js"></script>
<!-- application -->
<script type="text/javascript" src="index.js"></script>
</head>
<body style="padding:20px;"></body></html>
The next one is the javascript code that creates the login form and submit button, index.js:
Ext.onReady(function(){
var login = new Ext.FormPanel({
labelWidth:80,
frame:true,
title:'Restricted access',
width:230,
default:{autoHeight:true},
defaultType:'textfield',
items:[{
fieldLabel:'username',
name:'user',
allowBlank:false,
},{
fieldLabel:'password',
name:'pass',
inputType:'password',
allowBlank:false,
}],
buttons:[{
text:'Login',
handler:function(){
login.getForm().submit({
method:'POST',
waitTitle:'Connecting',
waitMsg:'Sending data...',
url:'/cgi-bin/login.cgi',
success:function(){
/* url must be changed to another CGI to
validade user's session */
var url = '/main.html';
window.location = url;
},
failure:function(form, action){
if(action.failureType == 'server'){
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Oops!', obj.errors.reason);
}else{
Ext.Msg.alert('Oops!', 'Authentication server is unreachable');
}
login.getForm().reset();
},
});
},
}],
});
login.render(document.body);
});
It does asynchronous POST to login.cgi, that is a python script. The interesting thing here is that FormPanel's submit does a standard POST to the script but expect a specific JSON data structure as response, according to the rules of Action.submit (http://extjs.com/deploy/dev/docs/?class=Ext.form.Action.Submit).
Below is the python code of login.cgi, that replies the expected JSON data structure:
#!/usr/bin/env python
import cgi, json
def err(message):
return (json.write({'success':False, 'errors':{'reason':message}}))
def auth(u, p):
""" here you need to implement session control and real auth mechanism """
if u == 'admin' and p == '123':
print json.write({'success':True})
else:
print err('Invalid username or password')
if __name__ == '__main__':
print 'Content-type: text/x-json\n'
form = cgi.FieldStorage()
if not form.has_key('user') or not form.has_key('pass'):
print err('No way.')
auth(form['user'].value, form['pass'].value)
Once this script replies with {"success":true} JSON data structure, FormPanel's submit success method is executed. In this example it's being redirected to main.html while in real scenario it should redirect to another CGI that at least check user's session before loading content.
Anyway, the next one is main.html with the logout button:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="ext-2.0/resources/css/ext-all.css">
<style rel="stylesheet" type="text/css">
.panel-items{margin:10px;}
</style>
<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="ext-2.0/adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->
<script type="text/javascript" src="ext-2.0/ext-all.js"></script>
<!-- application -->
<script type="text/javascript" src="main.js"></script>
</head>
<body></body></html>
Nothing special. At least it loads main.js, as follows:
Ext.onReady(function(){
var win = new Ext.Window({
layout:'fit',
width:500,
height:200,
closable:false,
buttons:[{
text:'Logout',
handler:function(){
Ext.Ajax.request({
url:'/cgi-bin/logout.cgi',
success:function(){window.location='/index.html';},
failure:function(){window.location='/index.html';},
});
},
},{text:'Hello world!'}]
});
win.show(document.body);
});
When the logout button is clicked it does asynchronous GET to logout.cgi, that should remove user's session from the server and guarantee that such user isn't authenticated anymore.
Here's a template of logout.cgi:
#!/usr/bin/env python
def remove_session():
pass
if __name__ == '__main__':
print 'Content-type: text/x-json\n'
remove_session()
That one should do the job, but you have to write your own session management or use something like Django to do that.
Well, as I'm new to ExtJS it may not be perfect, but from my point of view it's a nice way to do user authentication. I hope it helps. ;)
I assume that apache is configured properly and python extensions such as cgi and json are already installed.
Below is the first file, index.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="ext-2.0/resources/css/ext-all.css">
<style rel="stylesheet" type="text/css">
.panel-items{margin:10px;}
</style>
<script type="text/javascript" src="ext-2.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-2.0/ext-all.js"></script>
<!-- application -->
<script type="text/javascript" src="index.js"></script>
</head>
<body style="padding:20px;"></body></html>
The next one is the javascript code that creates the login form and submit button, index.js:
Ext.onReady(function(){
var login = new Ext.FormPanel({
labelWidth:80,
frame:true,
title:'Restricted access',
width:230,
default:{autoHeight:true},
defaultType:'textfield',
items:[{
fieldLabel:'username',
name:'user',
allowBlank:false,
},{
fieldLabel:'password',
name:'pass',
inputType:'password',
allowBlank:false,
}],
buttons:[{
text:'Login',
handler:function(){
login.getForm().submit({
method:'POST',
waitTitle:'Connecting',
waitMsg:'Sending data...',
url:'/cgi-bin/login.cgi',
success:function(){
/* url must be changed to another CGI to
validade user's session */
var url = '/main.html';
window.location = url;
},
failure:function(form, action){
if(action.failureType == 'server'){
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Oops!', obj.errors.reason);
}else{
Ext.Msg.alert('Oops!', 'Authentication server is unreachable');
}
login.getForm().reset();
},
});
},
}],
});
login.render(document.body);
});
It does asynchronous POST to login.cgi, that is a python script. The interesting thing here is that FormPanel's submit does a standard POST to the script but expect a specific JSON data structure as response, according to the rules of Action.submit (http://extjs.com/deploy/dev/docs/?class=Ext.form.Action.Submit).
Below is the python code of login.cgi, that replies the expected JSON data structure:
#!/usr/bin/env python
import cgi, json
def err(message):
return (json.write({'success':False, 'errors':{'reason':message}}))
def auth(u, p):
""" here you need to implement session control and real auth mechanism """
if u == 'admin' and p == '123':
print json.write({'success':True})
else:
print err('Invalid username or password')
if __name__ == '__main__':
print 'Content-type: text/x-json\n'
form = cgi.FieldStorage()
if not form.has_key('user') or not form.has_key('pass'):
print err('No way.')
auth(form['user'].value, form['pass'].value)
Once this script replies with {"success":true} JSON data structure, FormPanel's submit success method is executed. In this example it's being redirected to main.html while in real scenario it should redirect to another CGI that at least check user's session before loading content.
Anyway, the next one is main.html with the logout button:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="ext-2.0/resources/css/ext-all.css">
<style rel="stylesheet" type="text/css">
.panel-items{margin:10px;}
</style>
<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="ext-2.0/adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->
<script type="text/javascript" src="ext-2.0/ext-all.js"></script>
<!-- application -->
<script type="text/javascript" src="main.js"></script>
</head>
<body></body></html>
Nothing special. At least it loads main.js, as follows:
Ext.onReady(function(){
var win = new Ext.Window({
layout:'fit',
width:500,
height:200,
closable:false,
buttons:[{
text:'Logout',
handler:function(){
Ext.Ajax.request({
url:'/cgi-bin/logout.cgi',
success:function(){window.location='/index.html';},
failure:function(){window.location='/index.html';},
});
},
},{text:'Hello world!'}]
});
win.show(document.body);
});
When the logout button is clicked it does asynchronous GET to logout.cgi, that should remove user's session from the server and guarantee that such user isn't authenticated anymore.
Here's a template of logout.cgi:
#!/usr/bin/env python
def remove_session():
pass
if __name__ == '__main__':
print 'Content-type: text/x-json\n'
remove_session()
That one should do the job, but you have to write your own session management or use something like Django to do that.
Well, as I'm new to ExtJS it may not be perfect, but from my point of view it's a nice way to do user authentication. I hope it helps. ;)