JSF application giving 404 for a sub-context - jsf

I am working on a web application which uses JSF. I have a folder called 'admin' under 'web' and I have couple of jsp pages under folder 'admin'. I can access jsp pages under 'web' but when I try to access the pages under 'admin' I get '404-Requested resource cannot be found'
The 'context.xml' for my application is something like this:
<Context antiJARLocking="true" path="/MyApp"/>
This thing works on my local tomcat but when I deploy this to my web hosting providers tomcat I have above mentioned problem.
What exactly I need to do to fix this problem.
Here is server.xml for my application on the Hosting provides tomcat:
<Host name="myapp.com" appBase="/home/myapp/public_html">
<Alias>www.myapp.com</Alias>
<Context path="" reloadable="true" docBase="/home/myapp/public_html" debug="1"/>
<Context path="/manager" debug="0" privileged="true"
docBase="/usr/local/jakarta/tomcat/server/webapps/manager">
</Context>
</Host>
Or do I need to add URL-Mapping to my web.xml?
I have following servlet filter in the web.xml for '/admin/*' url-pattern
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>com.myapp.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
And the filter code is as follows:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
lgMgr.logDebug("doFilter() is called...");
String validuser = null;
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession(true);
//If authorization key not in session, redirect to login page.
validuser = (String) session.getAttribute(Common.AUTH_USER);
if(validuser != null) {
lgMgr.logDebug("doFilter(): User is allowed to access the page...");
//If the user is allowed access to the URI, let the flow proceed as normal
chain.doFilter(request, response);
return;
} else {
lgMgr.logDebug("doFilter(): User is not allowed to access the page, redirecting user login...");
//User not allowed access - redirect to login page
res.sendRedirect(req.getContextPath() + "/AdmLogin.jsf");
return;
}
}

Files in /WEB-INF are not public accessible. I have no idea why it works locally, but this violates the servlet specification. Also, JSF cannot forward views to JSP pages in /WEB-INF folder, they should be placed in public webcontent (one folder level up above /WEB-INF folder).

Related

JSF: Redirection [duplicate]

I have a JSF page which posts data to an external page.
The data is loaded from a JSF managed bean which generates a unique ID in the post data.
I have an issue where a user clicks on a checkout button then navigates back to the same page and presses the checkout button again. The post data has not updated. Moreover, the bean is not invoked at all. Is there anyway to force JSF to reload the page and the form data?
<form action="#{checkoutBean.externalUrl}" method="post"
id="payForm" name="payForm">
<input type="hidden" value="#{checkoutBean.uniqueID}" />
<input type="submit" value="Proceed to Checkout" />
</form>
That page is likely being loaded from browser cache. This is essentially harmless, but indeed confusing to the enduser, because s/he incorrectly thinks that it's really coming from the server. You can easily confirm this by looking at the HTTP traffic monitor in browser's web developer toolset (press F12 in Chrome/FireFox23+/IE9+ and check "Network" section).
You basically need to tell the browser to not cache (dynamic) JSF pages. This way the browser will actually request the server for the page (and hereby triggering proper creation/initialization of managed beans and so forth) instead of showing the previously requested one from its cache.
Generally, this is to be done with a simple servlet filter like follows:
#WebFilter("/app/*")
public class NoCacheFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(req, res);
}
// ...
}
Where /app/* is the example URL pattern on which you'd like to turn off the browser cache. You can if necessary map it on /*, *.xhtml or even on servletNames={"Faces Servlet"}.
If you happen to use JSF utility library OmniFaces, then you can use its builtin CacheControlFilter by just adding the following entry to web.xml (which demonstrates a direct mapping on FacesServlet, meaning that every dynamic JSF page won't be cached):
<filter>
<filter-name>noCache</filter-name>
<filter-class>org.omnifaces.filter.CacheControlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>noCache</filter-name>
<servlet-name>facesServlet</servlet-name>
</filter-mapping>
See also the showcase.
I found a solution that works for JSF without having to create a servlet-filter. Just put the line below to your .xhtml page.
<f:event type="preRenderView" listener="#{facesContext.externalContext.response.setHeader('Cache-Control', 'no-cache, no-store')}" />

Prevent remote access of a web page

Is it possible to prevent remote access of a web page?
Let's say I have my page1 (home page) which is obviously accessible anywhere via its url. Then I have page2 (admin page) which I would only like to be accessible from the machine where my web application is deployed.
This may sound like this kind of scenario. Only, instead of the admin console, page2 should not be accessible remotely.
Please be more precise what are you using?
I assume that you don't use any framework, so you have only serlvets and .jsp pages.
First,put you adminpage.jsp to WEB-INF folder. Content of this folder is not visible out of your application (without your permission).
Second, create filter that will intercept your requests to servlets (Try to use servlets for all requests, don't use direct links to .jsp pages, because this is only way to add some security. These servlets should be like controllers in MVC). To create Filter you need to add class that will implement interface Filter
public MyFilter implements Filter {
...
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
if (request.getRemoteAddr.equals("your server address") {
filterChain.doFilter(request,response);
}
}
...
}
You see, if IP address is equal as your server address is, this request will be proceed further. Filter interface has more two methods init() and destroy() and you can leave them blank. To connect your filter with your servlet add to your web.xml following.
<filter>
<filter-name>myFilter</filter-name>
<filter-class>fullPackagePath.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/url-to-the-admin-panel-servlet</url-pattern>
</filter-mapping>
Of course you need to have servlet with url that will forward to the admin.jsp page.

Logout user - Java EE 6 Security

I have one servlet representing secure content, annotated as follows:
#WebServlet(name = "GreetingServlet", urlPatterns = {"/greeting"})
#ServletSecurity(
#HttpConstraint(
rolesAllowed = {"TutorialUser"} ) )
and web.xml as below:
<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">
<display-name>hello2_basicauth</display-name>
<!--other servlet names and mappings are defined via annotations-->
<security-role>
<role-name>TutorialUser</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>file</realm-name>
</login-config>
</web-app>
when I've entered the /greeting path for the first time, username/password prompt appeared ( earlier I have created users for Jboss using add_user.sh).
After inputing right credentials I was able to see the secure content offered by the servlet.
The problem now is that whenever I access the /greeting path again, I'm no longer asked for the credentials.
I have implemented below logout servlet:
#WebServlet(name = "Logout", urlPatterns = "/logout")
#ServletSecurity(
#HttpConstraint(
rolesAllowed = {"TutorialUser"} // 403 if user not present ... // default add user to file realm and assign to TutorialUser group
)
)
public class Logout extends HttpServlet {
public static final Logger logger = Logger.getLogger(Logout.class.getCanonicalName());
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("---- Principal = " + request.getUserPrincipal());
request.logout();
logger.info("---- Principal = " + request.getUserPrincipal());
}
}
however it doesn't work ( I can still access resource at /greeting without logging in).
Console logs this when accessing /logout:
INFO [servlets.Logout] (http--127.0.0.1-8080-4) ---- Principal = duke3
INFO [servlets.Logout] (http--127.0.0.1-8080-4) ---- Principal = null
Yes, this is the way BASIC authentication works. Roughly the sequence is:
With BASIC authentication, the browser remembers the protected resources and the credentials and sends them back with every request to the protected resource.
The server creates the session and authorizes the user based onthe session cookie, despite the fact that the credentials get sent again (so the server does not have to look at the database every time, just once per session).
The logout servlet gets called and correctly destroys the session. But, with the next request to the protected resource, the browser sends the credentials and the server transparently logs the user back in! (You can verify that by checking that the session cookie has changed after the logout.)
What can be done?
Embrace the way things work, i.e. adapt your logic to BASIC authentication.
Use FORM authentication (prettier and works as you seem to expect).

PrimeFaces redirect after Glassfish Login

I am trying to add PrimeFaces to my project. It is running on Glassfish 3 with form-based authentication. I downloaded the jar and put into WEB-INF/lib. After logging in, I was shown a css file with the URL:
localhost:8080/[webapp]/javax.faces.resource/theme.css.jsf?ln=primefaces-aristo
This does not happen if I disable security check. Here is the login part in my web.xml.
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsf</form-login-page>
<form-error-page>/login.jsf?failed=true</form-error-page>
</form-login-config>
</login-config>
Can anyone tell me what is the problem? Thanks!
This is caused by the restricted pages being cached by the browser.
The container managed security will redirect to the last HTTP request which triggered the authentication check. In your case it's apparently the auto-included PrimeFaces theme CSS file. That can happen if the browser has loaded the to-be-authenticated page fully from the browser cache, while the browser has loaded the CSS file fully from the server side, or have tested the cache validity of the CSS file by a conditional GET request. The container managed security will then remember exactly this URL as redirect-after-successful-login URL.
You'd like to exclude the JSF resources (<h:outputScript>, <h:outputStylesheet> and <h:graphicImage> from authentication checks. You could do that by excluding the common URL pattern /javax.faces.resource/*.
<security-constraint>
<web-resource-collection>
<web-resource-name>Allowed resources</web-resource-name>
<url-pattern>/javax.faces.resource/*</url-pattern>
</web-resource-collection>
<!-- No Auth Contraint! -->
</security-constraint>
You also need to instruct the browser to not cache restricted pages to prevent the browser loading it from the cache (e.g. by pressing back button after logout). Map the following filter on the same URL pattern as the one of your <security-constraint>.
#WebFilter("/secured/*") // Use the same URL pattern as <security-constraint>
public class NoCacheFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response);
}
// ...
}
Note that this also fixes the "back button" problem. So the enduser would also not see the restricted pages anymore when back button is pressed after signout/logout as would happen in your current setup.
You should exclude web resources from validation. Add for example <url-pattern>*.css</url-pattern> in your <security-constraint> element. Do that for all web resources which don't need security checks (js, images, ...).
it seems like you have the wrong url-pattern in your security constraints.
Have a look at this example for a working version.
http://blog.eisele.net/2011/01/jdbc-security-realm-and-form-based.html

Xhtml pages and HttpSession test , no jstl?

I have a dynamic web application in Java EE with JSF, Facelets, Richfaces.
My pages are all xhtml pages.
So JSTL isn't working in it.
For my account pages and all other private pages to be reachable, I want to test if the user got connected, so if the attribute session in HttpSession is not null. If it's null, the user gets redirected in the welcome page.
I tried in my xhtml page :
<jstl:if test="${sessionScope['session']==null}">
<jstl redirect...>
</jstl:if>-->
but as it's not jsp page it won't work. So where am I supposed to test if the session is not null to allow the user to see his private pages ?
in a central managed bean ?
The normal place for this is a Filter.
Create a class which implementsjavax.servlet.Filter and write the following logic in the doFilter() method:
if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
// Not logged in, so redirect request to login page.
((HttpServletResponse) response).sendRedirect("/login.jsf");
} else {
// Logged in, so just continue request.
chain.doFilter(request, response);
}
Map this filter in web.xml on an url-pattern of something like /private/*, /secured/*, /restricted/*, etc.
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.example.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/private/*</url-pattern>
</filter-mapping>
If you have the private pages in the /private folder then this filter will be invoked and handle the presence of the logged-in user in the session accordingly.
Note that I renamed attribute name session to user since that makes much more sense. The HttpSession itself is namely already the session. It would otherise been too ambiguous and confusing for other developers checking/maintaining your code.

Resources