Hi,
A short introduction is probably in order as I just subscribed to the list and to bring my proposal into context. My name is Sampo Savolainen and I work for the Information Centre for the Ministry of Agriculture and Forestry in Finland. We have decided to use WFS and WMS as the protocols to deliver spatial features and map images to our apps. Geoserver was chosen to be the WFS server and we have been working together with OpenGeo to strengthen the integration between Geoserver and Oracle.
Because of the nature of our applications, we need to impose strict authentication and authorization rules on the WFS layers. We are using our own authentication and authorization backend and my job is to integrate this system to Geoserver. My first attempt was a very involved and overly complex ServletFilter which had to analyze the requests and filter responses according to the users authorization information. This approach works but is clunky, error prone and performs sub-optimally. I now started work on another approach based on DispatcherCallback and DataAccessManager mechanisms.
The basic flow is that the user authenticates out-of-band in relation to geoserver. After successful authentication, the user receives a token which he/she must present with each WFS request. To be compliant with standard WFS clients, I want this token to be presented as a GET parameter to all WFS services. My problem is that Geoserver does not know of this token when it describes its’ services: the onlineResource fields in getCapabilities response messages, the schema locations in the responses to getFeature etc. etc. This can of course be handled with a ServletFilter which recognizes URLs in the responses and transforms them accordingly. However it is not an optimal solution.
What I’m suggesting is a callback system which is called whenever Geoserver creates URLs. Like DataAccessManager is called to check whether the current user can access a certain resource, this URLConstructionCallback would be called whenever a URL is constructed. It can then decide to modify the URL if necessary.
I think this addition could prove useful not only to me, but it could be useful on a more generic level. In fact, Geoserver already has a need for such a system: “proxified urls”. Currently there’s a utility method to proxify URLs: org.geoserver.ows.util.RequestUtils.proxifiedBaseURL(). This method seems to be called everywhere a URL pointing back to geoserver is created. I think this mechanism would be much better suited to a callback system. There’s also a ReverseProxyFilter which I’m not that familiar with but it seems like it’s doing the same thing. This callback system could remove the need for the filter altogether if I’ve understood its’ purpose correctly.
A rough sketch of the proposed API:
public interface URLConstructionCallback
{
public enum URLType {
EXTERNAL, // The link points outside Geoserver
RESOURCE, // The link points to a static resource (image, ogc schema, etc.)
SERVICE // The link points to a dynamic service provided by Geoserver (WFS, WMS, WCS, etc.)
};
public void constructUrl(StringBuffer url, Map kvp, URLType type);
}
The constructUrl() callback method could modify the base url and/or the key-value-pair map. The URLType parameter and Request, Service and Response objects (which are available through ThreadLocals via static methods, right?) would provide information about the function and context of the URL in construction.
The kvp could be optional and we could allow GET parameters to be already present in the URL string. This could make the use of such API easier.
The utility method for creating URLs would iterate the URL over spring registered callback objects:
public String constructURL(String baseUrl, Map kvp, URLType type)
{
if (urlConstructionCallbacks == null || urlConstructionCallbacks.size() == 0) {
return appendGetParameters(url, kvp);
}
StringBuffer tmp = new StringBuffer(url);
for (URLConstructionCallback callback : urlConstructionCallbacks) {
constructUrl(tmp, kvp, type);
}
return appendGetParameters(tmp.toString(), kvp);
}
// helper methods could be created to shield using classes from importing the URLType enum.
public String constructExternalURL(String baseUrl, Map kvp)
{
return constructURL(baseUrl, kvp, URLType.EXTERNAL);
}
Comments? Improvements to the API?
Thanks for reading,
Sampo Savolainen