Thursday, March 18, 2010

GWT and Spring / Acegi Security

Using Spring Security with GWT is fairly easy . . . just protect your GWT page and its associated servlets.

But one tricky thing is handling expired logins. When your user's login expires, they may be in the middle of using your web application. They will probably click some widget that will generate a call to the server. Because the login has expired, Spring Security will return your login page instead the expected server response. So you need to set up your GWT client code to handle this.

I got some good tips on how to do this on this page, but to make the ideas contained there a little more concrete, let me give some example code.

In my case, I wrapped the DisplayCallback class from the GWT Presenter library, but you should be able to apply these ideas to any gwt AsyncCallback.


/**
 * This is a special version of DisplayCallback that will handle Spring/Acegi
 * security errors.  If a 403 Access Denied errors occurs, the user will be
 * shown an error message.  If the server returns a Login page, that means the
 * user's login has presumably expired, so we direct the browser to redirect
 * to our login page.
 * 
 * Credit for these ideas comes from here:  
 * http://www.dotnetguru2.org/bmarchesson/index.php/2007/04/23/technical_tip_using_acegi_with_gwt
 * 
 */
public abstract class MyDisplayCallback<T> extends DisplayCallback<T> {

 private static final String SERVER_ERROR = "An error occurred while "
  + "attempting to contact the server. Please check your network "
  + "connection and try again.";

 public StatProjDisplayCallback(Display display) {
  super(display);
 }
 
 @Override
 protected final void handleFailure(Throwable cause) {
  
  doCleanup();
  
  String errorMessage = cause.toString();
  if (errorMessage.indexOf("403") != -1)
  {
   // Access denied for this role
   Log.debug("login invalid for this resource");
   if (GWT.isClient()) {
    Window.alert("Access denied");
   }
  }
  else if (errorMessage.indexOf("Login") != -1)
  {
   Log.debug("login expired, showing login dialog");
   if (GWT.isClient()) {
    Window.Location.assign("login.jsp?relogin=true");
   }
  }
  else
  { 
   Log.error("Handle Failure:", cause);

   Window.alert(SERVER_ERROR);
  }
  
 }
 
 /**
  * This method can be overriden to include code that should run in case the server call fails.  
  * This method will be called by handleFailure()
  */
 protected void doCleanup() {};

 @Override
 protected abstract void handleSuccess(T value);

}

0 comments:

Post a Comment