How can I check if servlet request is internal with Jetty? - java

We have a embedded Jetty 10.0.12 server, configure everything programmably (no web.xml) and already have a few servlets registered. We want to add a new servlet for an internal API. I have already done this. We now want to secure it. Security would be pretty simple: if the request did not come from within the server, reject it. This is good enough because we employ other security standards in the other servlets. I know where to start: create and register a filter:
public class InternalFilter implements Filter {
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
// TODO: Check if request is internal.
// I.e., came from another registered servlet in the same JVM.
// If it is internal, then `chain.doFilter`.
}
}
I do not know how to proceed from here.

I'll start by assuming that "internal" means you are using either RequestDispatcher.include() or RequestDispatcher.forward().
If so, then you can check the HttpServletRequest.getDispatcherType() value.
Value
Meaning
DispatcherType.FORWARD
Request arrived from a call to RequestDispatcher.forward().
DispatcherType.INCLUDE
Request arrived from a call to RequestDispatcher.include().
DispatcherType.REQUEST
Request arrived from the beginning of the server handling tree.
DispatcherType.ASYNC
Request arrived from call to HttpServletRequest.startAsync()
DispatcherType.ERROR
Request arrived from error handling (either an unhandled exception, or from a call to HttpServletResponse.sendError()

Related

Calling Java methods with React locally

How can i create a full web application with Java and React without having to create a rest API, not even a private API with username:password authentication.
I want it to be as it is created with JSP.
Is it possible call Java methods with react locally ?
Or even creating a restfull API that can only be called locally
Thank you
I don't think it's possible to communicate with Java in a client library such as React without having to create a HTTP API.
But you could make one and add a bit of extra layer of security to ensure that only your application could call your Java API by checking the remote address of each call and verifying that's the caller is indeed your server.
You can do this in Java using the getRemoteAddr() method from the HttpServletRequest object.
The best way to do this is to create a filter class that map all the API links and verify the remote address in each calls and then decide if it should allow it or not.
Here's an example:
import javax.servlet.*;
public class RequestFilter implements Filter{
public void init(FilterConfig config) throws ServletException {}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
String callerIp = request.getRemoteAddr();
if(callerIp.equalsIgnoreCase("MY-SERVER-IP-ADDRESS")) {
chain.doFilter(req, res);
}
else {
((HttpServletResponse)res).sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied !");
return;
}
}
public void destroy() {}
}
Replace "MY-SERVER-IP-ADDRESS" with your server ip.
And to map all the calls, set the filter tag in your web.xml as follows:
<filter>
<filter-name>RequestFilter</filter-name>
<filter-class>com.myPackage.requestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This should satisfy your need, but if you found another way please share it with us.
the first request is no, as far as I'm aware. But as for the local rest api, I know most web servers can check CORS headers and restrict to only serve certain origins on answering requests. So whichever JRE Web Server you're using, check it's API for accessing the origin in the request header, and route those to the rest code.

Restricting access to localhost for Java Servlet endpoint

In short - I would like to add such service endpoints to my servlet that can only be called from localhost. The restriction should be coded in the servlet itself, i.e it should not depend on Tomcat/Apache to be configured in a certain way. At the same time, there are many other, existing endpoints that should be reachable externally.
Longer description - I am creating an HTTP API that 3rd parties can implement to integrate with my application. I am also supplying a default implementation, bundled together with my app, that customers with simple requirements can use, without having to implement anything.
The endpoints of my default implementation should be reachable only for my app, which happens to be the same servlet as the one supplying the implementation, i.e it runs on the same host. So for security reasons (the API is security related), I want my implementation to be usable only for my app, which in the first round means restricting access to localhost for a set of HTTP endpoints.
At the same time, I don't want to rely on customers setting up their container/proxy properly, but do the restriction in my servlet, so that there are no changes required for existing installations.
So far the only idea I had was to check the requestor's IP addess in a servlet filter - so I am wondering if there is a better, more sophisticated way.
I think you should add Web Filter to your application and check your url in doFilter method. Check request.getRemoteAddr() and endpoint link you can put in urlPattern.
Like this:
#WebFilter(urlPatterns = "/*")
public class RequestDefaultFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (isForbidden(request, response))
return;
else
chain.doFilter(request, response);
}
}
isForbidden implementation is up to you. In response you just send 403 error code for example.
You can check make same check in servlet and send in response 403 error.

Get Request Parameters from XML using WebFilter

I´m developing a Web Service, using Glassfish, using SOAP. I have several web methods, and I want to get introduce my webmethod name and his parameters to http head request.
For example:
I have this path:
context: WebServices
webMethod: makeSomething
parameters:a=2
So I create a class named ProfilingFilter:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, javax.servlet.ServletException {
if (request.getContentLength() != -1 && context != null) {
((HttpServletResponse) response).addHeader("Operation", -->PATH+PARAMETERS);
// ((HttpServletResponse) response).addHeader("Operation", -->makeSomething?a=2);
}
}
It´s possible to use servlet response or servlet request to get this information?
If not, How can I do this?
You will need to access the HTTP request body. There is only one caveat: You can read a stream only once which means you will have to do some tricks in order to keep the SOAP request working. Take a look here:
http://wetfeetblog.com/servlet-filer-to-log-request-and-response-details-and-payload/431
This example covers reading a HTTP request and then passing the original data down the filter chain.
HTH, Mark

How do I avoid creating a session?

My setup is as follows
A main application servlet accessible under /myApp/mainServlet/
A little "hand made" soap proxy that adds security headers (usernames, passwords) to soap calls coming from a client
A Flex client that talks to the main servlet (through a BlazeDS interface), and sends some soap calls to a third party through this soap proxy
The flex client has a session id which is set when it first talks to the main servlet and it returns a HTTP header such as "Set-Cookie: "JSESSION: something; Path=/myApp". This cookie is then sent the the server to inform of which session the client is associated to.
The problem is that the little soap proxy also returns a cookie with a session id (for each call made through it) - and the Flex client then uses these cookies when talking to the main servlet. These other session ids are unknown to it, and then of course nothing works ...
I do not want a session cookie to be returned from the soap proxy, and I have verified that the problem would be solved by doing so by telling an Apache front-end to strip all "Set-Cookie" headers coming from the soap proxy. Unfortunately (due to some setup restrictions), this is not a way I can go in production, and so I will need to fix it programmatically.
How can I make the servlet not try to set any session ids? I believe I have seen ways of telling Jetty (the app server) not to send sessions ids, but that would also affect the main servlet's ability to do so as well, and is also not portable.
The proxy servlet is a very basic Spring Controller (just implementing the interface), so basically just a bare bone servlet.
Removing the cookie can be done with res.setHeader("Set-Cookie", null);
Edit: It is good to know, that this removes all cookies, since they are all set in the same header.
I recommend that you don't do it in your servlet, a Filter is better, because it's less intrusive, something like:
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
HttpServletResponse res = (HttpServletResponse) response;
try
{
chain.doFilter(request, res);
}
finally
{
res.setHeader("Set-Cookie", null);
}
}
This solution is inspired by this article at randomcoder.

Redirecting the response from a filter throws an IllegalStateException

I am writing a filter that will handle all authentication related tasks. My filter is a standard servlet filter as shown below
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
UserSession attribute = (UserSession)request.getSession().getAttribute("user_session_key");
if(attribute!=null && attribute.isValid())
{
//proceed as usual,
chain.doFilter(req, res);
return;
}
else
{
//means the user is not authenticated, so we must redirect him/her to the login page
((HttpServletResponse)res).sendRedirect("loginpage");
return;
}
}
But when I do this, I get an IllegalStateException thrown by Tomcat's ResponseFacade. How do I acheive this in a filter. I read in other SO threads that in TOmcat this is a problem as the response object is already commited. How do I get past this ?
Perhaps you have other filters defined that are executed before this one in the filter chain. That/these filters may be using the response so that it is not in a legal state for redirect at the time the execution reaches your filter.
Move your filter declaration at the top of filter declarations.
Are you committing the response somewhere else in the filter chain? Usually this is not done until you start writing to the response's OutputStream in the servlet itself. In your filter method you are however either forwarding the request to the next element in the filter chain or eventually the servlet itself, or you are sending a redirect, which at this point should be ok unless a previous filter already has (perhaps indirectly) committed the response.
Your filter looks fine, another filter must be running before your filter and committing the response.
Make sure that your filter-mapping elements are in the order you'd like them applied, the order of the filter definition elements doesn't matter.
To make sure that this is not the problem, try removing all other filter-mappings.

Categories