Filter intercepting the RPC for authentication.

176 views
Skip to first unread message

vladimir.lapacek

unread,
Mar 5, 2007, 11:35:25 AM3/5/07
to Google Web Toolkit
Hi,

I would like to create authentication for my application. I use
currently Filter, which simply redirects to the login page, when the
user is not logged in or the login times out.

This however does not work well for the GWT RPC calls, because the
client RPC handler does not expect the redirect instead of the
ordinary response.

I was thinking of returning a custom made Exception instead of the
redirect from the Filter to cause onFailure and redirect on the
client. I am already using a subclass of AsyncCallback to handle the
responses, so the redirect will be simple here. The code to send the
Exception from the server to the client would be very similar to part
of the RemoteServiceServlet. However, now I would need to distinguish
between normal HTTP requests and RPC ones.

My question is: Is there a better way to handle this scenario in the
current GWT? If not, what can I use to identify RPC request easily?

Thanks,
Vladimir

Jason Essington

unread,
Mar 5, 2007, 11:49:11 AM3/5/07
to Google-We...@googlegroups.com
Sounds like you are on the right track. I do something very similar
(though I don't use a filter for it)

All of my gwt services are located in a path that begins with /
service/ so you could do something like that to distinguish between a
GWT RPC and any other request.

Upon receiving a request, I check that the user is logged in and that
their session hasn't expired. If there is a problem, I throw an
AuthenticationException. On the client my AsyncCallback catches the
exception, attempts to authenticate the user, and once successful,
resends the original RPC.

-jason

Granat

unread,
Mar 6, 2007, 5:08:50 AM3/6/07
to Google Web Toolkit
Hi Jason,
Is your original RPC resended automatically? In that case, I'm curious
how you do that. In my case, when I receive the
AuthentificationException I just let the user login again, but have no
idea how to resend the last rpc.

Thanks

Jason Essington

unread,
Mar 6, 2007, 11:10:21 AM3/6/07
to Google-We...@googlegroups.com
It is an interesting problem to be sure ...

I use a pattern where I make my AsyncCallback implement Command.
The callback itself actually knows how to create an instance of the
service and fire the request.
The super class (ApplicationCallback in my case) knows how to handle
re-authentication, and when it successfully completes, just fires the
command again.

a very simple example looks something like this:
public class WorksheetCategoryCallback extends ApplicationCallback
implements Command
{

private WorksheetCategoryTreeItem categoryItem;

public WorksheetCategoryCallback(WorksheetCategoryTreeItem item)
{
this.categoryItem = item;
}

protected void onSuccessSub(Object result)
{
if (result instanceof List)
{
this.categoryItem.setWorksheets((List)result);
}
}

public void execute()
{
WorksheetServiceAsync.impl.getForms(categoryItem.getCategory
(), this);
}

}

ApplicationCallback has some code like this in onFailure:
else if (caught instanceof AuthenticationException)
{
LoginDialog.getLoginDialog(caught.getMessage(), this);
}

which invokes the loginDialog (a singleton) and adds the just failed
RPC to the dialog's command queue. If several RPCs were running
concurrently, they will all fail and all be added to the queue.

The login dialog has a submit button which will run another RPC which
attempts to authenticate the user. This authentication RPC will
execute the loginDialog's command queue onSuccess:

public void onSuccess(Object result)
{
LoginDialog dialog = LoginDialog.getLoginDialog();
dialog.setUserCookie();
dialog.executeQueue();
dialog.hide();
...
}

Which re-sends (all of) the RPC(s) that caused the
AuthenticationException.

Another pattern I use is to stuff a singleton of the service
implementation as a static field into my Async RPC interfaces:

public static final String ENTRY_POINT = GWT.getModuleBaseURL() +
"services/WorksheetService";

public static final WorksheetServiceAsync impl = Impl.getInstance();

class Impl
{

private WorksheetServiceAsync instance;
private static Impl impl;

private Impl()
{
instance = (WorksheetServiceAsync) GWT.create
(WorksheetService.class);
((ServiceDefTarget) instance).setServiceEntryPoint
(ENTRY_POINT);
}

public static WorksheetServiceAsync getInstance()
{
if (impl == null) impl = new Impl();
return impl.instance;
}

}

That way, invoking an RPC is reduced to a single line of code:
WorksheetServiceAsync.impl.getForms(someParam, cb);

-jason

Luciano Broussal

unread,
Mar 6, 2007, 4:24:25 PM3/6/07
to Google Web Toolkit
Very interesting design Jason. this give me food to thought

Jason Essington

unread,
Mar 6, 2007, 4:56:10 PM3/6/07
to Google-We...@googlegroups.com
I forgot to mention that the whole process (calling an rpc that'll
handle reauthentication if necessary) is kicked off by doing
something as simple as:
new WorksheetCategoryCallback(categoryTreeItem).execute();
it is fully fire and forget. when (if) it completes the data is
updated in what ever way is defined in the callback.

and since they are by definition Commands, they can easily be created
and stuffed anywhere that a command is expected (MenuItem,
DeferredCommand), or multiple disparate RPCs could be built and
queued, the mechanism firing them needs to know nothing more than
that they are Commands.

It has turned out to be a very flexible pattern.

-jason

mP

unread,
Mar 6, 2007, 5:54:57 PM3/6/07
to Google Web Toolkit
Isnt it easier to just require the user to login as the first step of
the app. After all your GWT is no longer stateless, you can control
the workflow. Once they pass the login form they should have a session
on teh server and then can freely call any service.
There should be no need to try to reauthenticate a user, your filter
should just throw an exception if the session has timed out or the
user cheated and somehow got to your service without authenticating.

Granat

unread,
Mar 7, 2007, 8:08:42 AM3/7/07
to Google Web Toolkit
Thanks Jason for taking your time to explain, I would never have
figured this out by myself! Now off to implement this in my project :)

Just one thing that confuse me a bit. Doesn't ApplicationCallback need
to have 'implements Command'? And then let the subclasses implement
the execute() method?

Thanks

Jason Essington

unread,
Mar 7, 2007, 10:38:55 AM3/7/07
to Google-We...@googlegroups.com
Sure, but sessions timeout (the timeout is even configurable per
user). You don't want a user to be logged in for ever, especially if
they take off for lunch or something and accidentally leave an
important form up. You don't want to have an unauthorized user
modifying that form and submitting it while the authenticated user is
away from their desk.
So, if that does happen, user goes takes off for a bit, then comes
back, spends another hour updating a financial worksheet, then
attempts to submit it ... you don't want the user to have to redo all
that work just because he let his login timeout. so this was my
solution.

-jason

Jason Essington

unread,
Mar 7, 2007, 2:22:31 PM3/7/07
to Google-We...@googlegroups.com
my implementation does do that, yes ...
public abstract class ApplicationCallback implements
AsyncCallback, Command

Then I define separate onFailurePre, onFailureSub, and onSuccessSub
methods that the subclasses should implement if they want special
onSuccess or onFailure behavior ...
onFailurePre is basically a hook to override the default behavior,
onFailureSub is called if the regular onFailure is unable to handle
an exception, and onSuccessSub is called onSuccess (there is some
default onSuccess code to break endless loops and such)

-jason

fklomp

unread,
Mar 7, 2007, 5:38:52 PM3/7/07
to Google Web Toolkit
I guess you could let let the user re-authenticate again when coming
back after lunch/session timeout, without loosing any state
information.

The only thing you need is a service (or servlet) that is secured by a
security contraint (BASIC/HTTPS). Once the client (after all, GWT is
just a client application) tries to make use of a timed-out service,
the user will have to re-authenticate.

At startup, the application would have to authenticate in the
background on behalf of the user. See
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/573e0fe5445a6588
for a sample.

Frank

Edward

unread,
Apr 19, 2007, 9:39:38 PM4/19/07
to Google Web Toolkit
I think it is not a good idea, because if there are a lot of RPCs,
will do a lot of more work, I think the fail rpc shall store in
session, when relogin, then recall the RPC.

> >>> Vladimir- 隐藏被引用文字 -
>
> - 显示引用的文字 -

Reply all
Reply to author
Forward
0 new messages