In my Tomcat 7 web app, I had a servlet for private PDF files: if not logged in, forward the user to the login page; otherwise, use the default servlet to show the page.
#WebServlet(name="pdfServlet",urlPatterns={"/pdf/*"})
public class PDFServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (!isLoggedIn(request, response)) {
getServletContext().getRequestDispatcher("/login.jsp").forward(request, response);
} else {
getServletContext().getNamedDispatcher("default").forward(request, response);
}
}
}
Recently, I had to transfer the website to another host which uses Tomcat 6. I removed the #WebServlet annotation, which is not supported in Tomcat 6, and instead added the following to my app's WEB-INF/web.xml, as well as downgrading the servlet specification from 3.0 to 2.5:
<?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_2_5.xsd"
version="2.5">
[...]
<servlet>
<servlet-name>pdfServlet</servlet-name>
<servlet-class>com.myapp.PDFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>pdfServlet</servlet-name>
<url-pattern>/pdf/*</url-pattern>
</servlet-mapping>
</web-app>
However, though the forwarding still works when not logged in, I get a 404 error if the user is logged in, when the default servlet tries to serve the page. It still works fine on my Tomcat 7 version of the site, even with the modifications to the code to make it backward-compatible; it also works fine when the PDF servlet is removed, but then it allows anyone to access the private PDFs.
Why is the default servlet not correctly serving the pages in Tomcat 6 only?
It seems to be a bug in tomcat https://issues.apache.org/bugzilla/show_bug.cgi?id=50026
As suggested by #1" a filter can do the job, here is how it should look:
public class SampleFilter implements Filter {
FilterConfig config; //setter and getters ommited
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config=filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (!isLoggedIn(request, response)) {
getFilterConfig().getServletContext().getRequestDispatcher("/login.jsp").forward(request, response);
} else {
chain.doFilter(request, response);
}
}
I solved this by using a Filter instead of a Servlet. I am still curious about why the error occurs, though.
Related
In my application, I added secure flags to the session header using this solution: https://stackoverflow.com/a/16616225
I experienced the following problem:
It works when I deploy to the remote machine. I can connect to it, no problems!
It does not work on my local, because http://localhost:7001 is no longer valid, I need to use HTTPS connection (https://localhost:7001).
The question is that can I enable or know that I am deploying on my local and I will use HTTP connection instead of HTTPS? Like writing a switch case so that when I deploy it locally, I won't use HTTPS and when I deploy to remote server, I will use HTTPS?
public class SecurityFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
// wrap the response
HttpServletResponse response = new SecureCookieSetter((HttpServletResponse)res);
// touch the session, so that it is added to the response header
((HttpServletRequest)req).getSession();
response.setHeader("Set-Cookie", "JSESSIONID=" + ((HttpServletRequest)req).getSession().getId() + ";Path=/");
HttpServletResponse response = (HttpServletResponse)res;
chain.doFilter(req, response);
}
#Override
public void destroy() {
}
}
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>package.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
You get rely on request.getScheme() to know whether it's HTTP or HTTPS.
But, a better solution will be to make your local server takes HTTPS connections. This can easily be done by adding a self signed certificate to your local domain. You can go to this site and generate a self-signed certificate. This can then be placed either on the web server or on the application server.
My Struts 2 application currently loads resource when a request comes in for the resource(jsp,action). I what all resources needed, to be loaded once the application is first deployed unto the container to have fast response times. How can I accomplish this? [Note] I am using Tomcat as my Servlet Container.
Why don't you try to implement Filters... as Filter starts with the application once it loaded and it will probably be helpful in order to load the resources.
You can add up your code in init method as it will be initiated with the start of container.
public class TestFilter implements Filter
{
public void init( FilterConfig config ) throws ServletException
{
System.out.println( "PUBLIC Fileter Started." );
}
public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
throws IOException, ServletException
{
//DO NOTHING
}
}
And do add an entry in web.xml
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
Hi I have a context and i have a mapping problem with this context. When I put this to my web.xml
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
I can only access like this.
http://domain.com/sub-context/
but I wanna access like this
http://domain.com/sub-context
what should I do?
Edit: I saw that when i hit for http://domain.com/sub-context in browser it redirects me to http://domain.com/sub-context/ although i havent do anything special for that. Who is doing this. Weblogic?
Here is one way:
<filter-mapping>
<filter-name>RedirectFilter</filter-name>
<url-pattern>/sub-context</url-pattern>
</filter-mapping>
Then in RedirectFilter:
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
String redirectURL = "http://domain.com/sub-context/";
response.setHeader("Location", redirectURL);
}
Adapted from here: redirect through web.xml in google-app-engine
We have a Java EE 6 web application with JSF 2.0 running on Glassfish 3.1.
There we encountered a strange bug: the Mime type of the response header send by Glassfish to the client depends on the order of the allowed Mime types in the request header send by the Browser. So in some cases (depending on the browser), the Mime type of the response is wrong, resulting in a broken html page.
But it would take pretty long to explain that thing. So to workaround this problem we now want to do just one thing:
Force the response header type for the whole web-application to "text/html".
Currently, we do that with a Servlet Filter configured in the Web.xml:
#WebFilter("/BaseFilter")
public class BaseFilter implements Filter {
public BaseFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
configuration in web.xml:
<filter>
<filter-name>BaseFilter</filter-name>
<filter-class>com.company.web.filter.BaseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BaseFilter</filter-name>
<url-pattern>/*</url-pattern>
<!-- these patterns should match cached resources -->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
So my question is, is there a better way to enforce a specific response header, especially by just configuring it instead of implementing a ServletFilter?
Is there a Glassfish option to do that?
You can specify it in the default template by the contentType attribute of the <f:view>.
<f:view contentType="text/html">
Seems like a stupid question to which the answer would be "Don't use encodeURL()!" but I'm working with a codebase that uses netui anchor tags in the JSPs and I need to disable the writing of JSESSIONID into the URLs as it is a security risk.
In WebLogic, you can configure this by configuring url-rewriting-enabled in weblogic.xml (I know because I wrote that feature in the WebLogic server!). However, I can't find an equivalent config option for Tomcat.
Tomcat 6 supports the disableURLRewriting attribute that can be set to true in your Context element:
http://tomcat.apache.org/tomcat-6.0-doc/config/context.html#Common_Attributes
No setting comes to mind. But this is fairly easy to do by creating a first-entry Filter listening on the url-pattern of interest (maybe /* ?) and replaces the ServletResponse by a HttpServletResponseWrapper implementation where the encodeURL() returns the very same argument unmodified back.
Kickoff example:
public void doFilter(ServletRequest request, ServletResponse response) throws ServletException, IOException {
chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
public String encodeURL(String url) {
return url;
}
});
}
As found in https://fralef.me/tomcat-disable-jsessionid-in-url.html - There is a servlet spec feature to do this
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>