com.cedarsolutions.client.gwt.rpc.proxy.XsrfRpcProxy Maven / Gradle / Ivy
Show all versions of cedar-common-gwt Show documentation
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* C E D A R
* S O L U T I O N S "Software done right."
* S O F T W A R E
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (c) 2013 Kenneth J. Pronovici.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Apache License, Version 2.0.
* See LICENSE for more information about the licensing terms.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Author : Kenneth J. Pronovici
* Language : Java 6
* Project : Common Java Functionality
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package com.cedarsolutions.client.gwt.rpc.proxy;
import com.cedarsolutions.client.gwt.rpc.IXsrfTokenRpc;
import com.cedarsolutions.client.gwt.rpc.IXsrfTokenRpcAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.RpcRequestBuilder;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.rpc.XsrfToken;
import com.google.gwt.user.client.rpc.impl.RemoteServiceProxy;
import com.google.gwt.user.client.rpc.impl.Serializer;
/**
* Customized remote service proxy that knows how to make CSRF/XSRF-protected requests.
*
*
* When you request an RPC interface with GWT.create(MyRemoteService.class)
,
* GWT normally does some magic to implement an asynchronous proxy over your
* remote service interface. This class is a customized version of GWT's
* magic asynchronous proxy which knows how to set CSRF/XSRF token into the RPC
* call once the token is available. That way, RPC clients don't need to know
* anything about the way the service is actually invoked — it's all
* controlled by annotations.
*
*
*
* The customization is conceptually very simple: for every relevant remote procedure
* call, we want to insert a different RPC call that happens first. The first RPC
* call invokes an RPC and gets a cryptographic token that's needed by the real RPC
* call. Once we have the token, the real RPC call is made as usual. All of the
* fancy stuff happens in XsrfRpcProxyCreator.
*
*
*
* Proxy classes like this are never directly instantiated by the GWT
* infrastructure. Instead, they're used as the basis for other concrete proxy
* classes that are generated by the GWT compiler. The GWT generator
* infrastructure generates other classes that extend this class, one concrete
* proxy implementation for each referenced remote service interface.
*
*
*
* Configuration for this class feels like a humongous hack. I would like to
* make the XSRF RPC timeout configurable. However, there's no obvious way to
* do it. The proxy is instantiated on the client side at runtime, but there's
* no hook to set properties on the proxy when it's instantiated. I've fallen
* back on using the XsrfRpcProxyConfig singleton to hold the value. See notes
* in that class for more details.
*
*
* @see GWT RPC XSRF protection
* @author Kenneth J. Pronovici
*/
public abstract class XsrfRpcProxy extends RemoteServiceProxy {
/** Instantiates a new remote service proxy. */
public XsrfRpcProxy(String moduleBaseURL, String remoteServiceRelativePath,
String serializationPolicyName, Serializer serializer) {
super(moduleBaseURL, remoteServiceRelativePath, serializationPolicyName, serializer);
}
/**
* Get a properly-configured reference to the CSRF/XSRF token RPC.
* @return Asynchronous reference to the RPC, via the standard GWT.create() mechanism.
*/
public static IXsrfTokenRpcAsync getXsrfTokenRpc() {
IXsrfTokenRpcAsync remoteInterface = GWT.create(IXsrfTokenRpc.class);
((ServiceDefTarget) remoteInterface).setRpcRequestBuilder(new TimeoutBuilder());
return remoteInterface;
}
/** Callback to handle responses from XsrfTokenServiceAsync. */
@SuppressWarnings("rawtypes")
protected abstract class AbstractTokenCallback implements AsyncCallback {
private AsyncCallback callback;
public AbstractTokenCallback(AsyncCallback callback) {
this.callback = callback;
}
@Override
public void onFailure(Throwable caught) {
this.callback.onFailure(caught);
}
@Override
public void onSuccess(String token) {
XsrfToken xsrfToken = new XsrfToken(token);
setRpcToken(xsrfToken);
this.invokeRpcMethod();
}
protected abstract void invokeRpcMethod();
}
/** RpcRequestBuilder that sets a timeout. */
protected static class TimeoutBuilder extends RpcRequestBuilder {
@Override
protected RequestBuilder doCreate(String serviceEntryPoint) {
int timeoutMs = XsrfRpcProxyConfig.getInstance().getConfiguredTimeoutMs();
GWT.log("XsrfRpcProxy using timeout: " + timeoutMs + " ms");
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, serviceEntryPoint);
builder.setTimeoutMillis(timeoutMs);
return builder;
}
}
}