Prevent user going to pages through address bar - jsf

I have a web application. After user login, I want the user to navigate pages by clicking on buttons or links instead of manually changing the url on the browser address bar. I saw a few posts we can use security constraint to do so. I have this in the web.xml. But seems like it does not work.
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Restrict raw XHTML Documents</display-name>
<web-resource-collection>
<web-resource-name>XHTML</web-resource-name>
<url-pattern>/faces/*</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>

I really do not like this approach. There are a few things which user expect when using a web application and for the best user experience you should not try and change the way, users use the browser.
However, if you really want this, one of the following could be done:
You could instrument all of your links and intercept the click from javascript. When clicked, the interceptor should create a cookie which contains the path that the link was referring to. When the user requests a page, you should check if their cookie contains the requested url, otherwise redirect them to homepage.
You could generate a token for each url, and append it to the end of the url, so http://blabla.com/mypage would become http://blabla.com/mypage?token=298347287.
The token would incorporate information about the url and would have a timeout, after which it is no longer valid. Then you would check the validity of the token, which would verify that the user indeed clicked on the link, not just entered the url (note: it still could happen that the user enters the url containing the token by copying it from the link).

Related

Localization problems on JSF. Redirects wrong address [duplicate]

I am unable to set a default page that loads in the browser when I start a Java EE project using Tomcat 8.0 from Eclipse.
I am trying to learn JSF, so I followed this tutorial
Everything works fine, but I can only see the created pages when I right click on the login.xhtml or welcome.xhtml file and choose "Run As/Run on Server".
So far, all the other web applications I have created loaded default page when I started the entire project. The default behavior is to load index.html page (or maybe index.jsp if there is some). So I added index.html and index.xhtml pages into my WEB-INF folder in the project, hoping that at least one of them will be shown. However, nothing happens. The browser always shows just the page on localhost:8080/JSFFaceletsTutorial/ URL, but the page is white clean, not even an error message. I think I have been getting error 404 in the process of solving this issue along the way, however, I am no longer able to reproduce this error and I don't remember what caused it.
I found that it's possible to change the default starting page
However, it doesn't work for me either. Regardless if I edit the web.xml file or not, I am getting the same result.
What is even more puzzling, is that when I tried to change the web browser: "Window/Web Browser/..." it acted for a while differently in the external web browsers than in the internal Eclipse web browser. The internal had always blank page - but the external web browsers once managed to show the index.html page - but it was some outdated version. Despite I made absolutely sure that I edited it, saved the changes, restarted the server... and still, it showed me the outdated version of the page.
And even in this case, it still ignored the changes made in the web.xml file.
But when I am trying it now, it again shows blank white page in all browsers. I am not aware of any change I made except for editing web.xml file...
My guess is that the problem is in the JSF technology I don't fully grasp yet. It's because when I choose to run the login.xhtml and welcome.xhtml pages using right click "Run As/Run on Server", the URL of those pages are on localhost:8080: with path /JSFFaceletsTutorial/faces/login.xhtml and /JSFFaceletsTutorial/faces/welcome.xhtml. That is weird, because I don't have any directory "faces" in my project.
Typing all possible permutations of:
<welcome-file-list>
<welcome-file>faces/index.html</welcome-file>
<welcome-file>faces/index.xhtm</welcome-file>
</welcome-file-list>
in the web.xml didn't help either. It didn't help when I typed the full address there either.
Here are warnings I am getting in the console (I skipped the INFO log entries):
"Dec 19, 2014 9:39:55 AM org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:JSFFaceletsTutorial' did not find a matching property.
...
WARNING: JSF1074: Managed bean named 'loginBean' has already been registered. Replacing existing managed bean class type com.tutorial.LoginBean with com.tutorial.LoginBean.
Dec 19, 2014 9:39:57 AM org.apache.coyote.AbstractProtocol start"
I am not sure this is helpful though.
I am out of ideas now.
First of all, the <welcome-file> does not represent the path to the "default home page". It represents the filename of the physical file contained in the folder which you'd like to serve up as default file when a folder like /, /foo/, /foo/bar/, etc is requested.
So, in JSF 2.x flavor, that would basically be:
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
This way, if the enduser requests / and you have /index.xhtml, then it will be served. Or, if the enduser requests /foo and you have /foo/index.xhtml, then it will be served, etc. If there is no such file, then a 404 error will be returned.
Now, you appear to have mapped your FacesServlet on a prefix <url-pattern> of /faces/*. This is a leftover from JSF 1.0/1.1 ages and really not recommended these days. Perhaps you were reading an outdated tutorial targeted at JSF 1.x, or a poorly maintained tutorial which was originally written for JSF 1.x and then uncarefully updated for JSF 2.x instead of rewritten from scratch.
That tutorial did also not seem to have explained you some servlet basics. Namely, in order to get JSF components in the XHTML page to run and generate some HTML output, the FacesServlet has to be invoked when the XHTML page is being requested. When you request the XHTML page like so /index.xhtml, while the FacesServlet is being mapped on /faces/*, then it won't be invoked. The browser would then retrieve the raw unparsed JSF source code instead of the generated HTML output. You can see it by rightclick, View Source in webbrowser. You should have requested the page like so /faces/index.xhtml so that the FacesServlet can run and produce HTML output which the browser can understand and present.
That only doesn't go well together with welcome files. This totally explains why you get a "clean white" (blank) page when using index.xhtml as welcome file (some inferior webbrowsers like IE would confusingly prompt a download dialog because of missing/wrong content type on the response containing raw XHTML source code). The FacesServlet was simply not being invoked. Just get rid of the old fashioned /faces/* URL pattern and use the JSF 2.x minded *.xhtml URL pattern instead.
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
This way the welcome files should work and you can just open JSF pages by directly requesting its physical URL without hassling with virtual URLs. This was not possible in JSF 1.x because it would let the FacesServlet run in an infinite loop calling itself and cause a stack overflow.
See also:
JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?
Setting application URL on WAS server, where does /faces/ come from?
What is the difference between creating JSF pages with .jsp or .xhtml or .jsf extension
Why can web.xml welcome-file be located inside WEB-INF
How to use a sub-folder as web.xml welcome directory
As to those warnings, they are unrelated but quite googlable.
i think this will work
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.xyz.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.xyz.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<welcome-file-list>
<welcome-file>/main/login.xhtml</welcome-file>
</welcome-file-list>
<!-- <servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.xyz.servlets.login</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping> -->
</web-app>
You can set a default page in the web.xml file to have the facesServlet invoked in JSF in 2 ways:
<web-app xmlns="http://xmlns.xyz.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.xyz.org/xml/ns/javaee http://xmlns.xyz.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>facesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
or invoke the facesServlet directly from the welcome file like this:
<web-app xmlns="http://xmlns.xyz.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.xyz.org/xml/ns/javaee http://xmlns.xyz.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
I hope it helps somebody!

JSF page accessible without the folder name in path

I'm trying to restrict access to JSF pages based on user roles. I saw lot of examples using filter. So I'm good there. I tried to put my xhtml files within "secured" folder under webapp folder that I need to protect. one of the xhtml file that I need to allow access to "admin" users is newAuth.xhtml and I have it inside the "secured" folder. On my menu page for the link which accesses "newAuth.xhtml" I gave the path including the "secured" folder. So the page comes up with url "server:port/signer/secured/newAuth.xhtml". Now when I tried to remove the "secured" path from the browser url, it still displays this page. I have the below mapping for FacesServlet in my web.xml.
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
I'm not sure how to protect the page from displaying when the path /secured is removed from the url.
UPDATE:
Leo, may be I should have explained my problem better in first place.
I wanted to implement the security filter based on the path in the url. If the url has /secured and if the user is non-admin then I would redirect them to some default page. This was my idea and so I placed all the restricted xhtml to the secured folder under webapp folder. For example newAuth.xhtml is a restricted xhtml page which only admin should have access. This page was accessible by the below url.
"protocol://server:port/signer/secured/newAuth.xhtml"
Then I tried to remove the /secured from the url, but the same page displays. Somehow the JSF was able to find the xhtml even without the /secured path. This behaviour will go against my security filter logic which will look for /secured in the url path.

How to automatically redirect user to a protected page after login with j_security_check

I have a web application developed using JSF1.2 running on JBoss AS7. Except for the login page, all other pages are protected. I also have a custom FormAuthenticator valve that needs to get triggered as part of the authentication processs.
The login page uses j_security_check.
My core requirements are:
Present the user with the login page when the try to access a protected page (and take the user to the originally requested page after successful login).
If the user access the login page directly, take the user to a welcome page after successful login.
Requirement #1 works fine, when I attempt to access http://server.com/my-app/faces/protected1.jsp.
However, I get a 404 when attempting to access the web application by its context-root (i.e. http://server.com/my-app/).
I tried to use welcome-file attribute in web.xml and my web.xml looks as follows:
<welcome-file-list>
<welcome-file>/faces/protected1.jsp</welcome-file>
</welcome-file-list>
...
<!-- login config -->
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- security constraints -->
<security-constraint>
<display-name>protected1</display-name>
<web-resource-collection>
<web-resource-name>protected1</web-resource-name>
<url-pattern>/faces/protected1.jsp</url-pattern>
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>HEAD</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description>protected1Group</description>
<role-name>WebUserRole</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>WebUserRole</role-name>
</security-role>
I have 2 questions:
Am I on the correct track trying to get welcome-file to behave as the default landing page after login (when the user access either the context-root of my app or the login.jsp directly)?
Why does the same thing work flawlessly if I change the welcome-file to an unprotected jsp (e.g. hello.jsp that has no security constraints)?
Any ideas are much appreciated! Thanks.
It doesn't make any sense to me to have your welcome file protected. Normally that would be the home page of a site, which anybody should be able to see. Then, if they click on some link to a protected resource such as 'My Stuff', that would take them to /faces/mystuff.something, which would be protected, so there would be a login before they got there.

Avoid direct access to source code of JSF page

When I request /personal/faces/public/login.xhtml, then it works fine, but when I request /personal/public/login.xhtml without /faces I obtain the raw source code of the page.
I would like to avoid that people could see the source code of the page. How can I achieve this?
This is happening because you've specified /faces/* in your FacesServlet configuration in the web.xml. As a result, any file requested that does not match the specified url pattern will be served as a regular file with a GET request
Change that config to the following to ensure all JSF related requests go through the FacesServlet:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
This ensures all files with .xhtml extension will be processed before returning to the client.
While the above solution may solve the immediate problem, what you're experiencing points to a deeper security issue. It indicates that anyone with a browser can request and download artifacts from your web application deployment and possibly other parts of your filesystem. This is a security hole you will need to look into. The options vary depending on your App server

Trouble using h:link to navigate to page with non-default suffix

I've got a JSF 2 application running on glassfish and have just installed the caucho
quercus PHP implementation. With just a little configuration I can successfully serve
.php files from the server:
<servlet>
<servlet-name>Quercus Servlet</servlet-name>
<servlet-class>com.caucho.quercus.servlet.QuercusServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Quercus Servlet</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
What I'm not able to do is use h:link to navigate to a page that doesn't use the
default suffix (.xhtml). So when I have:
<h:link outcome="/hello.php"/>
I just get a WARNING: JSF1090: Navigation case not resolved for component j_idt48 in the server log (when the page is loaded), and no amount of fiddling with leading / seems to help. Is there a way to get h:link to work in this way or should I just use h:outputLink?
Thanks.
<h:link> is for JSF navigation cases only, and thus indeed can't be used to navigate to other kind of resources, even when those are served by Servlets in the same application (like *.php in this case).
As you already suggested yourself, just use <h:outputLink>.

Resources