Using original URL request for proxied HttpServlet Request - java

I have an Apache proxy which redirects requests to /foo/bar to a web app running on /foo. The problem is that I have a Servlet filter in my filter chain which requires the request to still be in the /foo/bar format. It is an authentication filter I can't change and this is resulting in incorrect redirects after login to /foo instead of /foo/bar.
Following other similar threads, I've attempted using RequestDispatcher.forward with a modified request and HttpServletResponse.sendRedirect to modify the URL. The first approach seems to skip the rest of my filter chain, and the second goes to the proxy which then modifies the URL back to /foo.
Is there any way around this. Ideally what I'd like is for just the authentication filter to get a /foo/bar request and the rest of the chain to get a /foo request.

Looks like HttpServletRequestWrapper was what I was looking for. Just needed to extend this and provide getRequestURI and getRequestURL overrides (rather like described here). Then needed to add filter mappings before and after my auth filter to convert the request URL/URI as needed.

Related

How to determine request is forwarded or not in java filters?

I need to log the request and response what user has requested. Currently am using filters and logging the request in doFilter() method. But if i forward the request from one servlet to another servlet it is logging twice. I need to find out the forwarded request and skip log for that. Could anyone suggest how to find the forwarded request.
Use request.getDispatcherType(). In case of direct request it's request.getDispatcherType().name() be REQUEST, in case of forward - FORWARD

Using Spring, Tomcat, and Java, how do I redirect a request with HTTP headers?

So I have a org.springframework.stereotype.Controller and what I want to do is process the request normally if HTTP headers HA and HB are specified. But if the request has query parameters QA and QB specified, I want to redirect the request WITHOUT QA or QB, but WITH HTTP headers HA and HB such that HA has the value of QA and HB has the value of QB.
For example, if the incoming request is HTTP GET ~/rest/mortgage with HTTP headers x-name=foo and x-date=bar, I would process that request as is. But if the incoming request is HTTP GET ~/rest/mortgage?x-name=foo&x-date=bar, I want to redirect to myself with the request HTTP GET ~/rest/mortgage with HTTP headers x-name=foo and x-date=bar.
By doing this, I can have a single code path dealing with both styles of making the HTTP request just by adding a simple check at the controller level. This is because I pass the HttpServletRequest around to various parts of the code, so if I have the consistency of always having HA and HB instead of QA and QB, it reduces the cyclomatic complexity of the code.
Is this possible? And if so, how?
If this is not possible, I can achieve my desired result by defining my own wrapper for HttpServletRequest that does the transformation for me, but that's not as elegant of a solution.
If you want to intercept the HTTP request you need to use a Servlet Filter.
In order to replace the URL you have to get the Dispatcher for the new URL, and then dispatch the request again with the forward() method.
Something like this:
servletRequest.getRequestDispatcher(modifiedURL)
.forward(servletRequest, servletResponse);
However, you are not explicitly allowed to modify the HTTP headers. The way around this is to wrap the request and have a proxy object that handles this, by extending HttpServletRequestWrapper. It already implements the HttpServletRequest so you shouldn't have any issues using it wherever you are interacting with the original servlet request.
You can simply extend it and add your own method like addHeader() and keep an internal Map or something of the extra artificial headers you are adding. Then you have to just override getHeaderNames() and getHeader() to also combine the original headers with your own extra ones.
The last thing you will need to do is wrap your original servletRequest in your new wrappedServletRequest in your Filter. So something like this (where WrappedServletRequest is your new implementation that extends HttpServletRequestWrapper):
WrappedServletRequest wrappedServletRequest =
new WrappedServletRequest(servletRequest);
wrappedServletRequest.addHeader("yourHeader", "yourValue");
wrappedServletRequest.getRequestDispatcher(modifiedURL)
.forward(wrappedServletRequest, servletResponse);
Remember to add your <filter> and <filter-mapping> of your Filter in your web.xml for it to work.
You might want to have a look at this article for more details. It has some more information as to why you have to do it this way.
I didn't try it myself, so comment below and confirm if you manage to get it to work.

problem in using <t:inputFileUpload>

I have followed this tutorial from BalusC for FileUpload. but setter isn't getting called
That can have the following causes:
The enctype="multipart/form-data" attribute is missing on the <h:form>. This is mandatory in order to be able to send files to the server.
The ExtensionsFilter is missing in web.xml or not properly mapped on the servlet name of the FacesServlet. This is mandatory in order to be able to parse the multipart/form-data request.
There is another filter in the request-response chain before the ExtensionsFilter which has already parsed the multipart/form-data request beforehand. For example, when you're using RichFaces4, such a filter will be auto-loaded without that you need to declare it in web.xml. Request bodies can be parsed only once, so the ExtensionsFilter would receive an empty request after such another filter.
There is another filter in the request-response chain before the ExtensionsFilter which has completely skipped the ExtensionsFilter by for example forwarding or redirecting the request.

Reject GET Method on j_security_check

Is there a way to only allow POST requests to j_security_check? I want to reject GETs.
I am using Form Based security and want to only allow Posts to j_security_check. If a login request is made via a GET, the request should be rejected.
Having been trying to do the same on a JBOSS(Tomcat) server due to security concerns of JAAS using GET methods I attempted various ways.
Using a web.xml security constraint on the url pattern /j_security_check to only use POST - This doesn't work for JAAS mechanism as it would for normal servlets.
Passing login details from the login page to an intermediate servlet which checked the request method and if not a GET then forwarding on to j_security_check. - This did'nt work and was over complicated.
Creating a Filter that would check the request method and only invoke on a POST message to j_security_check - This didn't work as JAAS is deeper in web container and is called before the filter mechanism.
Creating a Valve, which DOES get called before the JAAS.
By adding the following in the invoke method:
HttpServletRequest req = (HttpServletRequest) request;
if (req.getMethod().equals("GET")) {
log.warn("Someone is trying to use a GET method to login!!");
request.getRequestDispatcher("/login.jsp").forward(req, response);
throw new ServletException("Using a GET method on security check!");
}
This does work.
Yes you can reject the GET request. In the web.xml file in the security constraint section you can specifiy the http methods allowed. In the following xml the only method allowed for this security constraint is the POST method. j_security check will only allow the post method.
<security-constraint>
<display-name>Your security constraint</display-name>
<web-resource-collection>
<web-resource-name>Your resource name</web-resource-name>
<url-pattern>/The URL pattern</url-pattern>
<http-method>POST</http-method>
<web-resource-collection>
<security-constraint>
You would need to rephrase your question.
j_security check is typically used in the login page.
If you request a secured resource and you were not authenticated, you are automatically redirected to the login page (assuming the app is configured to use Form Based security)
If your resource should not be challenged for GET requests, follow what Doug has mentioned. For example, if you want to secure POST calls to myaccount (the pattern for a Servlet) then you would be redirected to the login page only when a HTTP Post is made while the GET request would be accepted even without a user authentication.
The implication is you want to allow authenticated users access to POST request while GET requests are permitted to everyone.
An alternative approach I am considering to implement:
Blocking all but POST requests to j_security_check in a reverse-proxy/loadbalancer like nginx/apache
E.g. on Apache 2.4 this works:
<LocationMatch ".*j_security_check">
AllowMethods POST
</LocationMatch>
If I would need more customization I could reimplement j_security_check with my own servlet using HttpServletRequest.login(...)

Guice servlet DSL, filter all but one URL

I want to filter all requests to my web application through my "SecurityFilter" which checks that a session variable "authToken" is valid. The problem is that in order to get this token you need to hit the "AuthServlet" which is at /auth.
I need to filter all servlets except the /auth servlet with my "SecurityFilter". How can I do this via guice-servlet?
I thought of trying to no avail...
filterRegex("!((.)*auth(.)*)").through(PortSecurityFilter.class);
^((?!/authorize).)*$ worked.

Categories