| « Hibernate ou JPA : l’embarras du choix ? | GWT: Hibernate inside ! » |
Technical tip : Using Acegi with GWT
Foreword : why english ?
In my opinion, a technical tip must be written in english to be useful to most people (not only French one). The design and architectures entries, which are longer and more complex, will probably stay in French, since I am not always very comfortable (as you will probably see it) with William Shakespeare’s language :oops:
Introduction
Acegi is a powerful security framework based on Spring that allows you to simply manage authentication and authorization.
You can find a lot of very good written tutorials on the web (like this one)
Working with GWT
Acegi works pretty well with GWT. Both the main HTML page and RPC call are filtered by the Security library with a simple configuration file.
In my opinion, the simplest way to integrate Acegi is to not manage the login page in your module, but in a separate HTML file (no need for a new GWT module!) like this one:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>My Login Page</title>
</head>
<body>
<h2>Please log in</h2><br>
<form method="POST" action="j_acegi_security_check">
Username: <input type="text" name="j_username"><br>
Password: <input type="password" name="j_password"><br>
<input type="submit" value="Log in >>">
</form>
</body>
</html>
I have noticed only two issues, since GWT is an Ajax framework and Acegi is designed for pages applications (like JSF): session expiration and identification for unit testing.
Session expiration
Ajax applications are not classic HTML applications: the whole page is neither reloaded nor redirected to a new one. Consequently, when HTTP session expires (by default, after 30 minutes), any subsequent RPC call will fail and your application will receive… the HTML login page as error cause |-|!
The best way is to properly handle the failure exception in your AsyncCallback for example by parsing the error message:
public void onFailure(Throwable caught)
{
String errorMessage = caught.toString();
if (errorMessage.indexOf("403") != -1)
{
// Access denied for this role
//
Window.alert("Access denied");
}
else if (errorMessage.indexOf("Login") != -1)
{
// Session expired : display login form
//
LoginDialog.show();
}
else
{
// Other error
//
Window.alert("Error : " + errorMessage);
}
}
The login modal dialog allows the user to near seamlessly continue his navigation in the application.
Of course, you can factorize this code in a clean abstract class :>>
Testing
Finally, GWT implements a test unit framework, based on JUnit. It permits you to test the behaviour of the client code, including asynchronous RPC calls (cf the relevant documentation). Nevertheless, the GWT TestCase has one serious limitation: since the test code is compiled in JavaScript, it must be “GWT-JRE compliant”. That means that you cannot call any third party code in you GWT test, and especially Acegi TestAuthenticationProvider.
The only way I found to make it works is to call the authentication form from the test case, throught Java Script Native Interface:
/**
* Log on Acegi with GWT
*/
protected static native void login(String user,
String password)/*-{
$wnd.open("j_acegi_security_check?j_username="+
user+"&j_password="+password, "login");
}-*/;
Every test case method must then call the loginAs method at the very beginning of its execution.
public void testSearchAgent()
{
login("admin", "admin");
…
}
It stills open an empty browser window, but the Unit test is then authenticated.
Last tip…
If you want to launch your GWT unit test from Eclipse, don’t forget to add your ‘test’ folder as source directory in the <Module>.gwt.xml file and to add the ‘src’ and ‘test’ folders in the classpath of the JUnit test (Run… ->Classpath->Advanced…->Add folder…)
4 commentaires
I'm attempting to use Acegi with a login.jsp. But have been unable to get either a login.jsp, or a login.hml page to render in hosted mode. (Either directly or after the Acegi filter redirects after failing to find valid credentials.)
The GWTShell seems to be attempting to locate a module for the jsp/html, rather than just letting Tomcat render the jsp.
Did you have to do anything to get the login.html to render in hosted mode?
Any help would be much appreciated.
The login.html page must be in the GWT 'public' folder, so the embedded Tomcat server can find it.
Regards
Brun
Is there the same kind of framework working with php?
Thank you for your help!
Les commentaires sont fermés pour cet article.