I'd like to know if anyone has a solution to access resources of a website through a servlet only.
I have all my resources under WEB-INF. In other words, I don't want users to have direct access to any of my resources.
You can use ServletContext#getResource() for that.
URL resource = getServletContext().getResource("/WEB-INF/file.ext");
File file = new File(resource.getPath());
// ...
You can even use ServletContext#getResourceAsStream() to get an InputStream directly:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/file.ext");
// ...
As you can see in the examples, the ServletContext is available in servlets by the inherited GenericServlet#getServletContext() method.
That said, the phrase I don't want users to have direct access to any of my resources. is a bit contradicting. You're serving those resources by a servlet anyway? A servlet is directly accessible by URL. How is that different from "direct access"? Or do you just want to control the access based on some conditions? I'd say, a Filter is more suitable for this task.
Usually one would only fully hide the JSP files from direct access. In a Servlet which acts as front controller (according the MVC pattern) you could then forward requests to JSP files using RequestDispatcher#forward() which you in turn can obtain by ServletRequest#getRequestDispatcher().
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
You can hide jsp from the end user. In fact, you don't even have to deploy original jsp files with your web application, you can precompile them:
http://tomcat.apache.org/tomcat-5.5-doc/jasper-howto.html#Web%20Application%20Compilation
And the only way to hide html/js/css files is not to use them. Anything that's sent to the browser can be viewed there.
Related
I have a simple web app that allows the user to upload and access files. When the user accesses an uploaded file, the server needs to support all of the header types such as Accept-Ranges so that partial-content responses can be made on large media files. The DefaultServlet (in Tomcat) handles everything well in its serveResource() method called by doGet(), so I would like to use the DefaultServlet for the uploaded files. This is easy enough in normal circumstances since it is the DEFAULT servlet, but unfortunately for my case, I am unable to find a way to use the default servlet.
In order to prevent the uploaded files from being deleted when the webapp is redeployed, I need to store them outside of the webapp directory.
These files should only be accessible to the user that uploaded them, so I created a javax.servlet.Filter to handle resource access authorization. I know that if I add a new context in server.xml for the external resource directory, they will be accessible, and the DefaultServlet will be used.
<Context docBase="/path/to/resources" path="/resource" />
But I do not want to do that because then I am required to invasively modify server.xml which is not recommended (for reasons), and when a context exists for the /resource path, my filter for that url-mapping will not be invoked. So I do not think creating a new context is a good solution.
The only other solution I can think of would be to create a servlet for all requests at '/resource/*' which extends DefaultServlet, and somehow override functionality that would instead get the requested file at its actual external location rather than returning 404 on the non-existent resource in the webapp.
However, I have not been able to find an easy way to convert the DefaultServlet into one that can fetch files external to the webapp directory. Maybe there is a way?
How would I go about handling this?
Not an answer
In order to prevent the uploaded files from being deleted when the
webapp is redeployed
It means you are re-deploying your stuffs wrong(in a very bad manner), probably using war files, or worse(worst) tomcat manager.
I know that if I add a new context in server.xml for the external
resource directory, they will be accessible, and the DefaultServlet
will be used.
You are right, but you are wrong about having another context, it's not necessary.
Solutions:
Dear Michael-O specified the easiest and probably best answer.
You may also implement something like DefaultServlet too, sometimes(not for your case) it's better to implement things from zer0 rather than configuring and maintaining many too much complex stuffs.
I am working on an application that is deployed on a cluster of JBoss servers accessible via a load balancer. There is a set of data originating from another external service that I would like to expose as part of my application. But since this service is load sensitive, I would like to call this service from a separate standalone Java application only from one instance on regular intervals and put the data in a file which will be statically accessible over HTTP by the container itself. However, since this file will exist only one instance, if a request is routed to any other instance in that cluster, it will result in a 404 File Not Found. So this means that I need to make this file accessible on all instances.
One approach that I was considering was to have a servlet with the servlet mapping url pattern exactly as the file name that will hold the data. If the instance on which a request lands is the one instance where the file exists, it should serve the file or else it should be picked up by the servlet with the same url pattern as the file which will fetch the file from the one instance where the file exists and return that in response.
However, when I use the same url pattern for a servlet as a static file, the servlet is picked up first and the static resource is not looked up at all. Is there a way I can tell the webapp to look for the static resource first before looking up the servlet?
Second approach that I could think of was to use a filter with the same url pattern that will check for the existence of the file and if the file exists, let the container handle it or else get the file from instance where this file exists and return the same back in the response.
Can you think of any other approaches and the pros and cons of each before I decide which approach to take forward?
I'm working on a small web application that contains some JSPs, Servlets and static HTML pages. There are also some filters to implement a small authentication/authorization mechanism. My questions are:
How can I map an entire directory of JSPs to another? Here's an example: I want to map all the URLs like localhost:8080/WebAppName/pages/*.jsp to localhost:8080/WebAppName/*.jsp . How can I do that without writing an entry in the web.xml for each JSPs page in the directory 'pages'?
After having mapped these URLs to new ones, what do I have to write in the tag of in the web.xml? The mapped URL (WebAppName/*.jsp) or the real one (WebAppName/pages/*.jsp)?
Thanks in advance.
You could make a servlet - or JSP - that has a mapping *.xhtml (other extension). Using the request URI it can do a dynamic include of the corresponding JSP from pages.
In servlet:
String pagesPath = "pages/" + ...;
request.getServletContext(pagesPath).getRequestDispatcher().include(request,
response);
I doubt it is a good idea, as it does not add something: you might even need to adapt all JSPs (other extension). Or rename the JSPs to .jspf.
In general I use JSPs under WEB-INF/jsp or so; so they are not publicly accessible. And use a similar technique: creating a model in the servlet, and then to the view as JSP.
i want to tell my java servlet to ignore calls for static files, for example, if the file exists - just return the actual file without actually loading the servlet.
in my example i have a MyServlet in netbeans, and under the "web pages" directory i placed image.jpg.
next, i generated a .war file and placed it under tomcat/webapps
when i try to make a request to localhost:8080/MyServlet/image.jpg - the file is not loaded, the servlet is executed instead.
what i want is that if the file exists - it will return it, otherwise will run the servlet.
is there a quick way to implement it?
Mapping your servlet to / or /* is not the standard way for implementing servlets. In general you map global (controller) servlets to a path like /myServlet/*. Tomcat's default servlet is already available to serve your static content. It's configured in <tomcat>/conf/web.xml. Extract from inline documentation:
<!-- The default servlet for all web applications, that serves static -->
<!-- resources. It processes all requests that are not mapped to other -->
<!-- servlets with servlet mappings (defined either here or in your own -->
If you follow the above mentioned approach URLs in your application may look like this:
Static resource: http://myserver/myWAR/images/image.gif
Your servlet's URLs: http://myserver/myWAR/myServlet/* (* := wildcard)
Of course, more complex options like offloading static content to an external web server are available. You can override the standard configuration as well, but in most situations this is not necessary (at least in my experience).
Normally you'd handle this via your servlet mapping or by putting your static resources away from your servlet mapping.
Otherwise, if the request is mapping to your servlet, you either need to (a) check for the file in the servlet, and redirect to the real filename or stream back the image yourself, or (b) write a filter that knows enough about your webapp's structure to see if the request should be handled by your servlet, or the container.
If you described your usecase it'd be easier to be more helpful.
For static files you most likely need just to use http://localhost:8080/image.jpg (i.e. without the MyServlet part in the URL)
I use Jersey for my REST API. I use JSP files for the views. I put my JSP view files in www/views/.... Now I'd like to forbid access to these views through simple HTTP request on their canonical URL.
What is the best way to forbid direct access to these JSPs from the client ?
Stick the JSPs under /WEB-INF in the WAR.
As johna has already said, if you put the .jsp files under WEB-INF this will prevent any access to them from the web directly.
If you want finer-grained security controls I would investigate a tool like Spring Security which will let you set up more complex security rules.