I need to block the direct access to the jsp pages.
I've set my web.xml like this:
<security-constraint>
<web-resource-collection>
<web-resource-name>My Hidden Pages</web-resource-name>
<url-pattern>/*.jsp</url-pattern>
</web-resource-collection>
<auth-constraint></auth-constraint>
</security-constraint>
but all the pages are still accessible by typing their address in the browser address bar.
How can I solve this?
FYI I'm using jetty-maven-plugin and servlet-api 2.5
thanks
You don't hide jsps that way.
There are a few common approaches (best choice first)
Precompile your JSPs during build time, and don't include the actual JSP files in your WAR file.
Put your JSP file in the WEB-INF folder somewhere. Access to the jsps are then done via a Controller servlet. This uses the security of WEB-INF to prevent direct access to the JSP files, something that all servlet containers must honor.
See past stackoverflow questions on this:
Why put JSP in WEB-INF?
How can I hide the JSP file in WEB-INF folder?
There are many more, just search for "jsp in web-inf" to discover more about this concept.
Properly configure Jetty's JSP implementation. Once done, this means all access to JSP files like must go through the that implementation's JspServlet.
See webdefault.xml for example of how this mapping is defined.
If you see an error or warning on startup about "No JSP Support for ", then you know you've not configured JSP properly, and that means all JSP files will instead be served in a static way.
Note: If you are using an older version of Jetty (anything older than version 7.6.16), or as using an older version of Java (anything older than 1.7_40), or are using Jetty on Windows (problem here is solved with Jetty 9.3.0 due out in the next month or so), then even this can be worked around.
Your <url-pattern> is incorrect. It should be <url-pattern>*.jsp</url-pattern> without the /. The allowed patterns according to spec are:
A URL pattern is a URI that is relative to the application context.
Patterns can include:
Path mapping, starting with / and ending with /* This pattern identifies any resource that starts with a given path, for example,
/catalog/* or /catalog/products/*
Extension mapping, starting with *. This pattern identifies any resource with the given extension, for example, *.jsp or *.gif
Default servlet mapping, containing only / This pattern identifies the default servlet of the application.
Exact matches This pattern uses a string that represents a specific resource, for example, /snoop is a servlet mapping and
/list/banner.jsp is a file mapping.
If you want to secure pages in given folder you need to use pattern like /folder/* , if you want to protect all pages use just *.jsp, if you want to protect all pages except index.jsp, you will need to add another constraint which allows explicitly access to the /index.jsp file.
Related
It says in the Oracle webapp documentation
If a resource matches a URL pattern in both a servlet-mapping and a
jsp-property-group, the pattern that is most specific applies
(following the same rules as the servlet specification).
Why can't both be applied? Say I don't want a user to go directly to a jsp file, rather have it go through a servlet first, which will then forward that jsp to the user. But I also want that jsp file to have a prelude, coda, etc. Is there a collision here that one of them has to win over the other?
If you don't want the user to hit your JSP, stuff it underneath WEB-INF. The container can see those JSPs, but nothing from outside can.
Then, you'll see, the Servlet will have one URL, while the JSP will have a separate, different URL.
The external URL, the one representing the Servlet, doesn't (necessarily) conflict with the URL for the JSP. You then code up the property group on the JSP file itself.
Your Servlet will do its processing, and then FORWARD to the JSP (it can not REDIRECT, since the JSP is buried in WEB-INF, and the outside world can not see it).
The property group mapping works against the URL of the resource your are FORWARDing to, the JSP.
So, there's no conflict here. Simply two different URLs, one taking the initial request (the Servlet), the other the rendered resource that you FORWARD too.
I have a web application that is functioning properly (servlets called) when I place the application folder in the {JETTY_HOME}/webapps directory.
If I place a copy of the web application in a sub folder of webapps, then all the static files are called when I browse to the site, but the servlets that I call via ajax are returning 404.
http://localhost/shlaa
calls /shlaa/CommentController.do correctly with no error.
http://localhost/mapapp/shlaa
returns 404 for the ajax call /mapapp/shlaa/CommentController.do
web.xml in both paths /WEB_INF folders contains the following
<servlet>
<servlet-name>CommentController</servlet-name>
<servlet-class>web.CommentController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CommentController</servlet-name>
<url-pattern>/CommentController.do</url-pattern>
</servlet-mapping>
The jetty.xml folder in {JETTY_HOME}/etc contains the following:
<Call class="org.mortbay.jetty.webapp.WebAppContext" name="addWebApplications">
<Arg><Ref id="contexts"/></Arg>
<Arg><SystemProperty name="jetty.home" default="."/>/webapps</Arg>
<Arg><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Arg>
<Arg type="boolean">True</Arg> <!-- extract -->
<Arg type="boolean">True</Arg> <!-- parent priority class loading -->
</Call>
In order to correctly deploy Java Web application to some Application Server or just simple Web Container (like in your case), the web app (also called web module) MUST have a specific structure. The top-level directory of a web module is the document root of the application.
Here is a Web Module Structure:
Now, what you define in <url-pattern> in web.xml file it is just a logical / virtual path for some servlet. Again, it is NOT a real path to the physical location of the servlet class, but a logical path - you make it up as you wish.
OK, now you must put your webapp with the right structure right in the webapps directory. For example, in the above picture Assembly Root symbolizes your webapp folder. So you take that folder either directly or you can make a WAR (Web application ARchive) and put it right under webapps directory. It's not that in webapps you have some directory and in that direcory there are several webapps. All web apps must be right under webapps directory.
So in your case, if your webapp folder has a name shlaa, you must put that folder right under webapp. Period.
Now quote from the official Java EE docs:
Mapping URLs to Web Components
When it receives a request, the web container must determine which web
component should handle the request. The web container does so by
mapping the URL path contained in the request to a web application and
a web component. A URL path contains the context root and, optionally,
alias:
http://host:port/context-root/alias
Setting the Component Alias
The alias identifies the web component that should handle a request.
The alias path must start with a forward slash (/) and end with a
string or a wildcard expression with an extension (for example,
*.jsp). Since web containers automatically map an alias that ends with *.jsp, you do not have to specify an alias for a JSP page unless you wish to refer to the page by a name other than its file name.
In your case, the URL to your webapp will be
http://localhost:8080/shlaa
Now qoute from the Jetty wiki docs (Jetty/Howto/SetContextPathto):
Using the WebAppProvider
The WebAppProvider's role is to look in the ${jetty.home}/webapps/
directory for any deployable applications (such as *.war), and deploy
them onto a context of the same name as the filename. For example, the
WebAppProvider deploys ${jetty.home}/webapps/MyApp-2.4.war into the
context /MyApp-2.4. There is also the special root.war reserved word
that deploys into the context / . While this is the easiest deployment
mechanism, it sacrifices control over deployment specifics.
To make the long story short just place your web app right under webapps directory to make everything work.
As for the <url-pattern> - feel free to define whatever patter you like.
NOTE: actually the are several ways to configure Jetty, i.e. XML configuration is not the only one. See Configuring Jetty for the details.
Quote from The Java™ Servlet SpecificationVersion 3.0:
Chapter 12 Mapping Requests to Servlets 12.1 Use
of URL Paths Upon receipt of a client request, the Web container
determines the Web application to which to forward it. The Web
application selected must have the longest context path that matches
the start of the request URL. The matched part of the URL is the
context path when mapping to servlets. The Web container next must
locate the servlet to process the request using the path mapping
procedure described below. The path used for mapping to a servlet is
the request URL from the request object minus the context path and the
path parameters. The URL path mapping rules below are used in order.
The first successful match is used with no further matches attempted:
The container will try to find an exact match of the path of the request to the path of the servlet. A successful match selects the
servlet.
The container will recursively try to match the longest path-prefix. This is done by stepping down the path tree a directory
at a time, using the ’/’ character as a path separator. The longest
match determines the servlet selected.
If the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that handles
requests for the extension. An extension is defined as the part of the
last segment after the last ’.’ character.
If neither of the previous three rules result in a servlet match, the container will attempt to serve content appropriate for the
resource requested. If a "default" servlet is defined for the
application, it will be used. Many containers provide an implicit
default servlet for serving content. The container must use
case-sensitive string comparisons for matching.
12.2 Specification of Mappings
In the Web application deployment descriptor, the following syntax is used to define mappings:
A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used for
path mapping.
A string beginning with a ‘*.’ prefix is used as an extension mapping.
The empty string ("") is a special URL pattern that exactly maps to the
application's context root, i.e., requests of the form http://host:port/<contextroot>/.
In this case the path info is ’/’ and the servlet path and context path is
empty string (““).
A string containing only the ’/’ character indicates the "default" servlet of the
application. In this case the servlet path is the request URI minus the context path
and the path info is null.
All other strings are used for exact matches only.
Example with your names.
Your webapp name is mapapp (it's the application root). You want your CommentController.do to be accessed via
http://localhost:8080/mapapp/shlaa/CommentController.do
Then (if all other requiremants like directory structure etc are met) in your web.xml you put the following:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Comment Controller</servlet-name>
<servlet-class>com.example.CommentController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Comment Controller</servlet-name>
<url-pattern>/shlaa/CommentController.do</url-pattern>
</servlet-mapping>
</web-app>
The first forward slash (/) in the above url-pattern symbolizes context root / context path (mapapp in this case).
This way it will work.
Here are some usefull links.
The Java EE 5 Tutorial:
Web
Modules
Configuring Web
Applications
The Java EE 6 Tutorial:
Web Modules
Configuring Web
Applications
Jetty
Deploying Web
Applications
Jetty Documentaion Wiki
Hope this will help you.
UPDATE
For the Jetty specific configuration see this link:
How to have a web app respond only on a specific port
Here's what I think is happening.
Just cloning your application shlaa in both the webapps root and the webapps/mapapp will not clone your servlets to a new location.
The static content works because those files are actually present at that location and Jetty will serve them given the right location
For servlets, the server will recognize only one location, the one inside shlaa/web/WEB-INF/classes
(since you cloned your app, I assume your clone will be something like shla/mapapp/web/WEB-INF/classes)
What you have to do is just modify your web.xml so that shlaa/mapapp is also recognized
e.g : (try some combination of below)
<servlet-mapping>
<servlet-name>CommentController</servlet-name>
<url-pattern>/mapapp/CommentController.do</url-pattern>
</servlet-mapping>
I have been developed a jnlp file, and it is working properly when client downloads it from his/her browser. No problem up to here, but client can also access to the jar files that my jnlp is referencing, and eventually download them.
I don't want my jars to be downloaded by others by writing the path from browser. I just want to make the jnlp is directly accessible from browser.
How can I fix this situation ?
There is no 'fix' for it. If the Jars are accessible to the JWS client that launches the app., they are also available by direct fetch.
You can use the provided JnlpDownloadServlet as a way to block access. The JnlpDownloadServlet (look for it in the samples provided with the JDK) will handle requests for Jar files and do a diff on them. If you setup your web.xml file like
<servlet>
<servlet-name>JnlpDownloadServlet</servlet-name>
<servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JnlpDownloadServlet</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
then all requests for the files in /app will go through this servlet. This will prevent users from doing a simple browse to see the available files, but if they know the file name they can still create a get request to fetch it through the servlet.
If that is a problem, then you can also put security on access to this servlet (as you would any other servlet) using the security-constraint settings in the web.xml. If you add that, then the javaws launcher will require the user to provide valid credentials before it will download the files. I used BASIC as the auth-method because I wasn't sure if the javaws client would honor any others.
What if you generate the jnlp dynamically via a JSP or servlet (see here an example)?
In this case you can write a filter that can implement a policy(based on a cookie?) for retrieving files. If the cookie is not set you can disable the download of jars.
See the following article: http://lopica.sourceforge.net/faq.html#cookies
I have a web application, which was designed and always worked under root context ("/"). So all css, js and links started with / (for example /css/style.css). Now I need to move this web application to some different context (let's say /app1). It is easy to change server.xml configuration file and bring up web application in new context app1 using [Context path=""] item. But web pages are broken because all links are now incorrect. They point to old root context /css/style.css instead of new app1 context.
Is there any magic way to fix this problem without fixing each link by prefixing with some "context" variable?
Used server - Tomcat 5. Application is written with Java and uses JSP, Struts2, Spring and UrlRewrite filter. More interesting is to hear real experience in fighting with such problems that theoretical debates.
Thank you.
P.S. I do not see how UrlRewrite filter can help me because it will work only in app1 context. So requests to links like /css/style.css will not be passed to it.
If you use URL rewriting to redirect ROOT to your application, won't that eliminate the ability to have a an application in ROOT? If so, what is gained by switching the context?
I think the general way to link resources is to either append a "context" variable and make the link absolute: ${pagecontext.request.contextpath}/css/style.css or just make the link relative: css/style.css
Unless you have specific reasons for being unable to modify the code, I would do a search/replace on the links and be done with it. You should have no more than three or four expressions to find, /css, /images, /javascript, etc.
You should always create urls via url re-writing, not only so that session info can be added to the url, if required, but also so that the context path can be added. You should create all urls as absolutely paths from the top of the application and then let url-rewriting handle adding the context-path to the front, as appropriate.
<c:url value="/css/site.css"/>
That will render /<context-path>/css/site.css or /<context-path>/css/site.css;jsessionid=134345434543 into a jsp file if they don't have cookies enabled. You can also use the c:url tag to render the url into a variable and then use that variable multiple times throughout your document. Just add a var="x" attribute to the tag and then ${x} will render the url into your doc. If you aren't using jsp to render your output, you'll need to find the appropriate mechanism for your view layer, but they will all have one. If you are rendering a url in java code, just take a look at the source code to the c:url tag and you'll see how it is done.
The one awkwardness is that CSS files (and js files) aren't processed, so urls in css and js files need to be relative paths or they will break whenever you change the context path. Most js already uses relative paths since library maintainers don't know what path you are going to install their library to. CSS backround images, on the other hand, are often specified as absolute urls, since the same CSS file may be included into html files at different levels of a file hierarchy. There is no easy fix for this that I am aware of other than to create appropriate symlinks such that the relative url always works or else serve up the problem CSS files via a JSP so that the urls can be rewritten as appropriate. I'm sure there are probably filters or apache modules you can run which will do the url replacement, but then you've still got to manually update your filter/module whenever you deploy to a new context path.
My Spring Dispatcher servlet url-pattern is /* (as spring MVC REST suggests)
Now all the request are resolved by this Servlet. even CSS/JS/Images also get resolved and handled by servlet..
So, Spring MVC tries to find controller.. :(
How to bypass this? Is there any standard way out of this problem??
& Don't want to change url-pattern to /rest/* (so, other static resources get accessed by /css/ or /js etc.)
You can map your controllers to a smaller set of URLS (i.e. /app/*), and then rewrite the URLs that your users actually see so that they don't even know about. Have a look at the mvc-basic webapp sample, particularly web.xml and urlrewrite.xml to see how this is done.
Map the Spring dispatcher to some subsection of the URL space, and use Tuckey to rewrite URLs the user deals with.
http://www.example.org/app/controller/action -> http://www.example.org/controller/action
Just a heads-up update on this: the default rewrite configuration as defined in the Spring sample did not work out of the box for me. The rewrite rules for stylesheets, scripts, etc. were still processed to the /app/* rule, and subsequently handled by the DispatchServlet, which is not desirable.
I had to add the last="true" attribute to the styles/scripts/images rules to indicate that other rules should not apply, and I had to use the FreeMarker Spring URL macro in any CSS/JS include paths.
Just in case someone encounters the same problem.