Read the request stream multiple times - java

We have a Tomcat ValveBase class implementation that is doing the authentication for our servlet container apps. One way to authenticate our http REST calls is to sign them and then check the signature on the server side. We do this check in the ValveBase class.
The problem is that after we consume the InputStream of the request (for validating the signature), we pass the request (org.apache.catalina.connector.Request) to the next valve implementation and by the time it hits the servlet, the inputStream is gone. No content to be delivered, since it was consumed at the signature verification procedure.
In the javax.servlet api, you can use an HttpServletRequestWrapper to implement your own ServletRequest and pass the real request as a constructor argument. In that case, we were able to avoid the situation where the content was read only once, but in the case of the catalina Request, seemed to be more delicate than we thought. Any ideas? Thanks.

There is a long standing enhancement request open against Tomcat to support wrappers for use in Valves in a similar manner to Filters.
The bug includes a patch that is likely to need updating for Tomcat 7.0.x.
Given that you are already using a custom valve adding the patch may not be too much of a leap. With that patch in place, you should be able wrap the internal Request object and solve this problem in a similar manner to the Filter solution (which I assume involves saving a copy of the request body - watch out for DoS issues).
This is, of course, completely untested. As an incentive to try it, if it does work and you provide the updated patch (attach it to the Bugzilla report) I'll look at getting it included in Tomcat 8.0.x and 7.0.x (providing it doesn't require any changes to the existing API).

Related

Reading multipart request in a filter without consuming the request itself

I'm stuck in a very weird problem.
I have a legacy application that I need to protect against XSS attacks. Someone before me added the classic filter/requestwrapper solution that overrides the getParameterMap and getParameterValues to clean parameter values from malicious scripts. The problem is that this works only on urlencoded forms, but when the request is from multipart-formdata forms that methods are not called, so the requestwrapper doesn't clean from that malicious code.
So I need to do the same thing but on multipart-formdata forms. After a long research I tried the following solutions:
I tried with #MultipartConfig annotation, but it works only on servlets, not filters.
I found that I can add allowCasualMultipartParsing=true in META-INF/context.xml , this allows the requestwrapper to work as with urlencoded forms but for some reason this breaks a page where the application does file uploads using a particular angular plugin, so this way is not applicable in my scenario.
So I tried to extend the filter itself, catching multipart form request and reading parameters with commons-fileupload to check for malicious scripts, but it seems to "consume" the request so the request is empty after the filter execution and the application breaks. I tried even to clone HttpRequest in order to work with a copy of the request using Gson but this caused application crash.
Do you have other ideas or suggestions? I only need to read form fields from multipart request without invalidating/consuming it. I'm stuck on this problem from weeks now.
Thank you in advance.
Best regards.

PATCH with contentType application/json instead of application/json-patch+json

i have a question about PATCH content type. my app is spring boot application which running on public cloud.
my concerns is if Patch verb could has the contentType to be application/json instead of application/json-patch+json?
any drawbacks if using plain-old json?
any drawbacks if using plain-old json?
Yes
Patch verb could has the contentType to be application/json instead of application/json-patch+json?
It can
That's not particularly useful
You might not care that it's not particularly useful
HTTP Patch says that we should be including in the request a patch document containing
a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version.
PATCH /foo HTTP/1.1
Content-Type: text/plain
Replace "ghoti" with "fish"
That's a perfectly well formed patch request, proposing an edit to the /foo resource
BUT: notice that there's some ambiguity in this example -- does this patch say to replace one instance of ghoti? or every instance of ghoti? If we want to ensure that the client and the server understand this message the same way, then they need some sort of agreement on that point.
Part of the point of REST is that these agreements should have readily standardizable forms.
Agreements about patch documents that are supported by a server are themselves described by the Accept-Patch header (defined in the HTTP Patch specification); the header values are media types; I can then find the definition of that media type to figure out how to describe my changes.
Furthermore, if the advertised media type is one I already know about, I can re-use my previous solution. Part of the point of having an application/json-patch+json standard, or an application/merge-patch+json standard, is that we all understand those documents the same way. So we get interop - any application/json-patch+json capable client can successfully communicate with any application/json-patch+json capable server.
application/json doesn't work this way, because there's nothing in the JSON specification that creates a common understanding of how to interpret a JSON document in a PATCH context. Instead, you need some other "out of band" information to do the right thing.
If interop isn't important in your context -- for instance, if you control both the server and the client implementation -- then aligning on some common standard isn't all that important either. Your web page hosts your java script that communicates with your back end, and so long as it is easy to coordinate changes here, it's not particularly important that the message schema use here match what is used elsewhere.
But if you instead are striving for "web scale" adoption, then you need to be to consider in your designs how to take advantage of general purpose work that has already been published.

HttpServletRequestWrapper and Filter lifecycle in tomcat

I am coding a Tomcat application and am authenticating against Google's oauth2 services. I was originally going to write a simple Filter to do the authentication but there is no way to set the user principal in a Filter. From my understanding you have to have the Filter call an implemented HttpServletRequestWrapper and set it inside of that class as seen in this post
I'm pretty sure Tomcat only instantiates one Filter of each type you may have defined and all requests go through this single object down the Filter chain (correct me if I'm wrong).
In the linked to code, is it correct for the code to call
next.doFilter(new UserRoleRequestWrapper(user, roles, request), response);
where every request is instantiating a new UserRoleRequestWrapper? Should this Filter instead have one request wrapper instatiated that gets shared amonsgst all requests? I'm having a hard time finding documentation on the specs of classes such as these.
I don't think that a Filter is what you're looking for. Doesn't seem right for this purpose... Filters weren't created for such use cases; they were created for pre/post processing requests and responses, with emphasis on manipulating the actual request/response data, rather than other aspects of the client-server communication (such as security). Remember, authenticating a user may have further repercussions than just handling HTTP request cycles. Security ties into the JavaEE framework in a lower level than HTTP cycles.
If you want to authenticate against oauth2, you should be far better off implementing some sort of a JAAS implementation for it, and plug it into Tomcat.

Can I write a Java loader class that will hook HTTP requests in the loaded class?

I have a class that I want to hook and redirect HTTP requests in.
I also have a loader class already written, but all it does it replace the functions that contain the HTTP requests I want to change.
Is there a way to hook HTTP requests in Java so that I can redirect them all more easily?
Sort of like a proxy-wrapper.
Clarification:
The app sends out a GET or POST request to a URL.
I need the content to remain the same, just change the URL.
DNS redirects won't work, the Host HTTP header needs to be correct for the new server.
PS: This is a Desktop App, not a server script.
A cumbersome but reliable way of doing this would be to make your application use a proxy server, and then write a proxy server which makes the changes you need. The proxy server could be in-process in your application; it wouldn't need to be a separate program.
To use a proxy, set a couple of system properties - http.proxyHost and http.proxyPort. Requests made via HttpURLConnection will then use that proxy (unless they specifically override the default proxy settings). Requests made using some other method like Apache HttpClient will not, i think, be affected, but hopefully, all your requests are using HttpURLConnection.
To implement the proxy, if you're using a Sun JRE, then you should probably use the built-in HTTP server; set up a single handler mapped to the path "/", and this will pick up all requests being sent by your app, and can then determine the right URL to send them to, and make a connection to that URL (with all the right headers too). To make the connection, use URL.openConnection(Proxy.NO_PROXY) to avoid making a request to the proxy and so getting caught in an infinite loop. You'll then need to pump input and output between the two sockets.
The only other way i can think of to do this would be to override HttpURLConnection with a new handler which steers requests to your desired destination; you'd need to find a way to persuade the URL class to use your handler instead of the default one. I don't know how you'd do that in a clean way.
While an older post, this should give some ideas of some kinds of bytecode injects which can be peformed: Java Programming: Bytecode Injection. Another tool is Javassist and you may be able to find some links from the Aspected-oriented programming wiki article (look at the bytecode weavers section).
There are some products which extensively dynamically modify code.
Depending upon what is desired, there may be ... less painful ... methods. If you simply want to 'hook' HTTP requests, another option is just to use a proxy (which could be an external process) and funnel through that. Using a proxy would likely require control over the name resolution used.
you can use servlet filters which intercept the requests, the requests can further be wrapped, redirected, forwarded or completed from here.
http://www.oracle.com/technetwork/java/filters-137243.html
Do you control all of the code? If so, I suggest using Dependency Injection to inject the concrete implementation you want, which would allow you to instead inject a proxy class.
If you can change the source code, just change it and add your extra code on each HTTP request.
If you can't change the source code, but it uses dependency injection, perhaps you can inject something to catch requests.
Otherwise: use aspect-oriented programming and catch to URL class, or whatever you use to do HTTP requests. #AspectJ (http://www.eclipse.org/aspectj/doc/next/adk15notebook/ataspectj.html ) is quite easy and powerful.

Is there a way to get raw http request stream from Java servlet handler?

I am trying to put some logging to capture the raw http request coming to my application. My Java code is inside a SpringMVC controller. I have access to the "HttpServletRequest" object. But I could not find a way to get the raw http request stream out of it. There is a reader but only reads the post content. What I want is the whole shebang, the url, the headers, the body. Is there an easy way to do this?
Thanks in advance.
No.
The servlet provides no such API, and it would be hard to implement because (basically) you cannot read the same data twice from a Socket. It is not difficult to get header information, but raw headers are impossible to capture within a servlet container. To get the bodies you need to capture them yourself as your application reads/writes the relevant streams.
Your alternatives are:
Write your own server-side implementation of the HTTP protocol. (Probably not right for your application.)
You may be able to get the header information you need with filters, though they don't show the raw requests.
Some servlet containers have request header logging; e.g. with Tomcat there's a beast called the RequestDumperValve that you can configure in your "server.xml" file.
Implement a proxy server that sits between the client and your "real" server.
Packet sniffing.
Which is best depends on what you are really trying to achieve.
FOLLOWUP:
If the "badness" is in the headers, the RequestDumperValve approach is probably the best for debugging. Go to the "$CATALINA_HOME/conf/server.xml" file, search for "RequestDumperValve" and uncomment the element. Then restart Tomcat. You can also do the equivalent in your webapp's "context.xml" file. The dumped requests and responses end up in "logs/catalina.out" by default. Note that this will give a LOT of output, so you don't want to do this in production ... except as a last resort.
If the badness is in the content of a POST or PUT request, you'll need to modify your application to save a copy the content as it reads it from the input stream. I'm not aware of any shortcuts for this.
Also, if you want to leave logging on for long periods, you'll probably need to solve the problem yourself by calling the HttpServletRequest API and logging headers, etc. The RequestDumperValve generates too much output, and dumps ALL requests not just the bad ones.
No, servlets provide no api to get at the raw request - you might need a sniffer like wireshark for that.
You can get at the parsed request headers and uri though:
getHeaderNames()
getRequestURI()
etc.
I managed to read my raw request in my webapplication deployed on Tomcat 5.5
All I had to do is to read HttpServletRequest through my servlet/Spring controller
using request.getInputStream() only.
It must be the first API approach to the request. before any filter or other command start to mass with the request that cause its completely reading by the webserver.
What's the problem with that approach?

Categories

Resources