I would like to set a particular page (one that does not require a user to sign in to use) to have a STATE_SAVING_METHOD of client rather than server while the rest of the pages use server. Is there a way to set it on a per-page basis?
I would like to do this to get around the dreaded ViewExpiredException.
There is no way. This is however been requested as new feature. See also JSF spec issue 1056.
To solve the particular ViewExpiredException issue, you need to look for alternative ways. You can just ask a new question here about specifically the issue you have. There are always ways to go around it.
The state saving method is set once in web.xml and is there for the whole app. If you don't want that particular view to expire you could do an ajax poll that "pings" the page in a specific interval of time and thus avoiding view expired exception. Kinda workaround but this is the way with stateful frameworks.
Related
I have a basic question about JSF ManagedBeans for which I can't find a answer.
Suppose I have a bean MyBean with two methods method1 and method2 and a JSF page with a command link
<h:commandLink action="#{myBean.method1}">
</h:commandLink>
Is it possible for someone to analyse the source code of the page and call method2 instead of method1?
Answer
No, this is not possible by design.
Reasoning
Technically the client can only tell the server "The user clicked a html element with a certain id".
This event is then processed by JSF on the server-side, the component with the corresponding id is looked up and in this case the method "#{myBean.method1}" is executed.
As you can see, the client can not[!] tell the server what to do with this event.
Sources
JSF 2.2 Spec - 3.4 Event and Listener Model
Caveat
JSF is stateful and there are multiple ways to hold this state. The default is to hold state information server-side (e.g. in the users HttpSession).
Another option is to transfer (encrypted) state to and from the client. This is still conceptionally secure, but there *might* be bugs with client side state saving. Such a bug *could* be exploitable to do something like you described.
Yes, it is always possible to modify code (or markup-language) on the client-side. Your "action" will be called through some forms and/or Javascript-Methods - everything visible to experienced users.
But that's not an issue of JSF-2 only - this applies for every language which allows insights from the client side.
You shouldn't apply "security through obscurity" (https://en.wikipedia.org/wiki/Security_through_obscurity) but rather make sure, that you can handle this on the server-side.
If a user, who has access to two urls modifies url1 to url2 - that's fine, why not? (Could be bookmarked) - But YOU should take care of the modified request, if he is not allowed to access url2.
I have a GWT application that resides within a single web page, which I believe is fairly typical. I am in the process of securing it, and I need advice on choosing a proper approach. My ultimate intention is to check for presence of authenticated session on every gwtrpc server call.
In the past when dealing with servlet/JSP-based web application, I used filter and filter-mapping definitions in web.xml. And that worked like a charm considering that such applications usually consisted of many web pages, and redirection to a login page went right along with it. But in case of GWT and its often-used single screen nature, I feel that overriding RemoteServiceServlet's processPost() function may be a better approach. My intention would be to check for presence of an existing session, and then throw an appropriate exception if needed. The client would then react accordingly (i.e. login popup, etc) by determining the course of action based on whatever exception is thrown back to it.
I am aware of other existing solutions such as Spring security, but I would really like to hear opinions on my idea. Thank you.
I don't think that you should check for an authenticated session yourself. Let the application container deal with that. Of course, in order to do that, you will need a login-config section and security constraints in your web.xml file.
A good way to secure specific parts of your application is to check (prior to the actual display of the screen) if the current user is allowed to. From your remote servlet you can call getThreadLocalRequest().getUserPrincipal() to get the actual user (null if not authenticated) and getThreadLocalRequest().isUserInRole("admin") to make the autorization.
Hope this is helpful for you !
In my Cake 2.3 app, I have an action that's called via ajax. Since I'm using the Security component, I had to use $this->Security->unlockedActions, otherwise the action would fail.
However, unlockActions doesn't work when $this->Security->requireAuth() is called. Is this a bug? Do I have a misunderstanding of how CakePHP handles security?
Why doesn't unlockActions override requireAuth?
SecurityComponent::requireAuth() adds that action to an array of required actions, stored in SecurityComponent::$requireAuth.
If you take a look at the Security Component's startup code, you'll find that SecurityComponent::_authRequired(), the method that checks the $requireAuth array, is called before the unlocked actions are even checked. I imagine if you require an action to be authorized, that should take precedence over telling the app that it doesn't.
I would still consider this a bug (or incorrectly documented), as it clearly states in the documentation:
There may be cases where you want to disable all security checks for
an action (ex. ajax request). You may "unlock" these actions by
listing them in $this->Security->unlockedActions in your beforeFilter.
This is a new feature so it might be good to open up a ticket explaining the confusion and see what the core team thinks about it.
I should also note here that disabling the Security Component for ajax requests isn't always necessary. I have several apps that successfully use the Security Component, along with CSRF checks, side-by-side with ajax.
Authentication is very different from security.
Security protects against several ways to hack into your website, while the auth components handles the clearance of your users. When a member is updating his profile, I do want to verify that it is a logged in member (authentication), but i might not want to use the security component for the action he is calling.
This is a problem I inherited. We have a JSF/RichFaces/Seam app, which for security reasons has no-cache set. The problem comes when users hit the back-button, causing a repost of a form. Sometimes (and it is inconsistent) the form re-POST after hitting the back-button sets the backing bean properties to null. When caching is set to private, this does not happen. Unfortunately, that is not an option.
I have been looking for a workaround for this, and I'm not sure there is one.
Does anyone know of a standard pattern to use for this?
Does anyone know of a standard pattern to use for this?
Yes, the Post-Redirect-Get pattern. Add <redirect/> to your navigation cases of interest to perform a redirect to a GET request after a POST. The back button would then go to the GET request instead. In JSF 2.x, you can also do this by adding ?faces-redirect=true parameter to the outcome.
It has however a disadvantage when your webapplication poorly developed in such way that you're sending POST requests from page-to-page instead of POST requests to self (preferably ajax-flavored). This way any request scoped bean is not available anymore in the redirected GET request.
Also, when you're using commandlinks instead of outputlinks for plain vanilla page-to-page navigation (e.g. menu links, etc), then those should be fixed to outputlinks. Using POST has totally no value here, they should be GET from the beginning on.
Ideally, for sure in JSF 1.x webapps, you should not have any navigation cases at all if you want optimal SEO, bookmarkability and user experience.
We recently upgraded a major platform from jsf 1.2 to 2.0. After upgrading we're getting several ViewExpiredException errors each hour. From reading up on the topic it seems that this is an expected exception when sessions expire, however we've reviewed the access logs and we are getting these exceptions even when requests are only 5 minutes apart in some cases.
My questions are as follows:
1) Other than session expiration, what other conditions might cause ViewExpiredException?
2) The exception we're logging doesn't contain much detail about the exact condition that is causing the exception (missing session, corrupt session, unable to restore a particular component). Is there a way to introduce additional logging to find out the very specific situation that is triggering this exception in each case?
Mojarra 2.0.4-b09
Tomcat 6
Using Memcached Session Manager for session replication
Any help is appreciated. Thanks!
Other than session expiration, what other conditions might cause ViewExpiredException?
The enduser has requested/created too much views within a session and is submitting to an old view. The default max views per session is 15. In other words, if the enduser opens 16 browser windows/tabs on a page with a form within the same session and submits to the first one, then the user can get ViewExpiredException.
The max views per session is configureable in web.xml by
<context-param>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>15</param-value>
</context-param>
See also Mojarra FAQ for other parameters.
Is there a way to introduce additional logging to find out the very specific situation that is triggering this exception in each case?
Not through JSF and/or a ViewExpiredException. The whole exception just means that the view is not present in the session anymore. This can in turn indeed have more underlying causes. Logging the session creation and destroy using a HttpSessionListener and logging the session attribute modifications by HttpSessionAttributeListener may be helpful.
Update as per the comments, pressing the browser back button on a cached page containing a form and then submitting the form thereafter could indeed also cause ViewExpiredException when the view is been expired. This can be solved in following two ways, preferably in a combination of them:
Instruct the browser to not cache the pages.
Do not use POST forms for plain page-to-page navigation.
For more detail, see this answer.