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
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
Thanks
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
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
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
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
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
> >>> Vladimir- 隐藏被引用文字 -
>
> - 显示引用的文字 -