Reputation: 2677
I am writing an OpenID filter based on the JOID library to allow applications to transparently authenticate against our local OpenID Server. Since OpenID works via HTTP redirects, I end up losing the original request object in the process, especially if it's a POST with a data body. Is it possible to save the request object in a way that I can reuse it later in the transaction, after the user has been authenticated? Even just saving the message body itself should suffice, as I can preserve the query URL easily enough with a roundtrip redirect (by using the OpenID's return-to-url).
I want to make this completely transparent to the underlying servlets, so they behave the same whether the user went through the OpenID flow for this particular request or just has a valid/authenticated local session.
Upvotes: 7
Views: 4083
Reputation: 2677
For what it's worth (and for anyone coming here in the future), after fighting with this for about another week, I ended up switching my app over to use Spring Security entirely instead of a standalone custom filter and it works great. The Spring Security framework handles a lot of the odd issues with redirects and postponed requests that I was starting to have to write on my own.
Thanks to everyone for their suggestions.
Upvotes: 0
Reputation: 1109132
Store the data of interest (request parameters, request attributes, etc) in a Map
in session scope by an unique ID as key which you add to the return-to-url.
String id = UUID.randomUUID().toString();
DataOfInterest data = new DataOfInterest(request);
Map<String, DataOfInterest> map = (Map<String, DataOfInterest) session.getAttribute("dataOfInterest");
map.put(id, data);
returnToUrl += "?token=" + URLEncoder.encode(id, "UTF-8");
// ...
And then when it comes back, use HttpServletRequestWrapper
to wrap the current request wherein you override the getParameter()
and consorts to return the original data of interest. Do this in a Filter
.
String id = request.getParameter(token);
Map<String, DataOfInterest> map = (Map<String, DataOfInterest) session.getAttribute("dataOfInterest");
DataOfInterest data = map.remove(id);
chain.doFilter(new HttpServletRequestWithDataOfInterest(request, data), response);
The HttpServletRequestWithDataOfInterest
can look like this:
public class HttpServletRequestWithDataOfInterest extends HttpServletRequestWrapper {
private DataOfInterest data;
public HttpServletRequestWithDataOfInterest(HttpServletRequest request, DataOfInterest data) {
super(request);
this.data = data;
}
public String getParameter(String name) {
return data.getParameter(name);
}
public String[] getParameterValues(String name) {
return data.getParameterValues(name);
}
// Etc, only when necessary.
}
Note: any obvious nullcheck handling etc is up to you.
Upvotes: 7
Reputation: 242716
For general purpose usage it would be more complex than save just a request body, you also need to save headers and so on.
You may check how it's implemented in Spring Security.
Upvotes: 2
Reputation: 308918
No, you can't save a request. But you can have your filter create a session and add the object to session scope. Objects that have access to the session can use any object they find.
Upvotes: 1