I am developing a small frontend application project with JavaServer Faces, I have to implement client side and server side validation. I'm using also Prime Faces, this framework that has client side validation and Bean validation. My qu4estions is this:
Is bean validation considered server side, since user's data is validated in the backing bean (Managed bean) or due to JSF works as MVC model in the front end, this is not considered server side and other techniques should be used.
Supposing Bean validation is not properly server side validation, what are the best ways to implement server side validation.
Any advice and clarification is welcome.
Thanks!
'Bean validation' is a proper server-side validation which is one of a number of validations that you can use in JSF. JSF has long has its own validations in the view but since JSR-303, Bean validation, was introduced, that is supported as well and many validations could be removed from the 'view' to the model.
Bean-validation is not the same as and should not be confused with doing manual validation in managed beans when e.g. calling setters or action methods. The 'validation' phase of JSF has then already passed, so returning messages becomes more difficult.
Since not everyting can be (easily) done in JSF-303, there sometimes still needs to be additional validations in JSF specific ones.
PrimeFaces client-side validation should be seen as an addition to the server side validations, it does not replace them. It can use many of the existing JSF and JSR-303 validations and antomaticaly execute them client-side without any work from you. For more complex validations, custom client-side validations should be developed as you'd need to with client-side frameworks as well.
From the PrimeFaces documentation:
PrimeFaces Client Side Validation (CSV) Framework is the most complete
and advanced CSV solution for JavaServer Faces and Java EE. CSV
support for JSF is not an easy task, it is not simple as integrating a
3rd party javascript plugin as JSF has its own lifecycle, concepts
like conversion and then validation, partial processing, facesmessages
and many more. Real CSV for JSF should be compatible with server side
implementation, should do what JSF does, so that users do not
experience difference behaviors on client side and server side.
Compatible with Server Side Implementation.
Conversion and Validation happens at client side.
Partial Process&Update support for Ajax.
I18n support along with component specific messages.
Client side Renderers for message components.
Easy to write custom client converters and validators.
Global or Component based enable/disable.
Advanced Bean Validation Integration.
Little footprint using HTML5.
So it is not a question of client-side OR server-side but whether you want/can use client-side validations to enhance user-experience so some of the (very few) downsides of JSF (round-trips for validations) is reduced.
Validations done in the Java Code(Managed Bean) on the server are server side validations.
Another direct means of validation could be f:validate (Refer)
Related
I have a web application which uses JSF 2.3 for the front end and offers also an API which is consumed by the front end with Jersey 2.29.1 running on a Tomcat 9 server.
The front end offers a login which will store the authenticated user in a #SessionScoped AuthenticationBean. The API methods should only be consumable if the user is logged in on the front end.
#Path("/service")
public class ApiService {
#GET
#Path("/data")
#Produces(MediaType.APPLICATION_JSON)
public String loadData() {
final AuthenticationBean authBean = CDI.current().select(AuthenticationBean.class).get();
if (authBean != null && authBean.isLoggedIn()) {
// Do business logic
}
else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
}
}
On the JSF page the API is consumed with a 'basic' jQuery AJAX call $.ajax() and updates some visual content based on the JSON response. The URL which I pass to the AJAX call is "#{request.contextPath}/api/service/data".
Everything works fine as expected, until I disable the cookies in the browser. If the cookies are disabled, the session ID is added to the URL (instead of being stored in a session cookie) by the servlet engine. So if I do not explicitly append the session ID to the URL for the AJAX call I have no access to the current session in the API service method, e.g. "#{request.contextPath}/api/service/data;jsessionid=#{session.id}" and therefore I can not check whether the user is logged in or not.
My question is now if I do have to add the jsessionid manually for every AJAX request or is there any other 'clean' possibility to pass the session ID to the service methods? Or do I have to access the session in any other way in the API service?
... explicitly append the session ID to the URL ...
The HttpServletResponse#encodeURL() does exactly that task, see also javadoc (emphasis mine):
Encodes the specified URL by including the session ID, or, if encoding is not needed, returns the URL unchanged. The implementation of this method includes the logic to determine whether the session ID needs to be encoded in the URL. For example, if the browser supports cookies, or session tracking is turned off, URL encoding is unnecessary.
So, basically:
#{request.contextPath}#{response.encodeURL('/api/service/data')}
The same method is by the way delegated by ExternalContext#encodeResourceURL().
Return the input URL, after performing any rewriting needed to ensure that it will correctly identify an addressable resource in the current application.
Jakarta Servlet: This must be the value returned by the javax.servlet.http.HttpServletResponse method encodeURL(url).
So, technically you can also do
#{request.contextPath}#{facesContext.externalContext.encodeResourceURL('/api/service/data')}
But this is a bit less convenient to type down. Moreover, using #{request.contextPath} already indicates that you're using JSF on top of servlets, not portlets, so using #{response} should be perfectly fine. You might want to make it yet shorter by defining a custom utility method in an application scoped bean. E.g.
#{functions.encodeURL('/api/service/data')}
#Named #ApplicationScoped
public class Functions {
public String encodeURL(String uri) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
return ec.getRequestContextPath() + ec.encodeResourceURL(uri);
}
}
This 'Answer' is not an answer to your real question but an explanation on why this is in no way JSF related (at the end there is a hint though to an answer)
JSF is an api and Jersey is an implementation of an api (JAX-RS). They effectively are complementary technologies and have no relation to one another in any way. It's the same like asking can I use JPA and Jersey in one application. Your actual questions have like stated no relation to JSF whatsover. JSF uses the session mechanism provided by the servlet engine, just like jax-rs does.
The second thing that is unclear is what your definition of 'front-end' is and where you run what. JSF in the JavaEE 'stack' is a front-end technology. JSF has a server side part in which you declare the components(See What is the definition of "component" in JSF) and when the html is generated they have client side html/javascript/css counterparts which communicate with the server in a way that is specified in the JSF specs. JSF 'components' by themselves do nothing if not backed by 'glue logic' on the server that in turn calls services (See JSF Controller, Service and DAO)
It might by now be clear that
is it possible for a JSF component to have called a Jersey service by an AJAX call?
is 'vague' and most likely given by your lack of knowledge of what the JSF is/does and how Jersey fits in (Jersey should be 'rest' here or jax-rs if you mean the api), See also How to implement JAX-RS RESTful service in JSF framework
JSF Components' html part on the client side communicates with the server in a JSF specific way, so
Rest is not needed there to get the client-side to communicate with the server (superfluous)
Trying to get rest in there makes things overly (overly) complex and without a real advantage
If you are trying to get the JSF server side components to communicate via REST
The server side is for interaction with the client side by means of the JSF spec for it
They are backed by code that in turn calls services. In this you can call a rest service, database or whatever
If, like I suspect, you want a non-jsf related $.ajax to call some rest service
You totally can, but read How to implement JAX-RS RESTful service in JSF framework
You can do anything with it to update the client side html
You can even update the html generated by JSF components
When doing 3, do NOT expect them to still work al the time, JSF is not to blame here
So after all this, your session id problem is not a jsf related problem. You'd have the same problem when using plain jsp or even plain html that has triggered a session.
HINT
So a better title would have been "jsessionid in url not added to ajax call in jquery" I posted this one in a search engine and added site:stackoverflow.com: jsessionid in url not added to ajax call in jquery site:stackoverflow.com
One of the results is effectively a duplicate of your question:
Appending my jsession ID at every ajax call by Jquery
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 done a small experiment with #FlowScoped beans, whose purpose, as I understand, is to make easier creating "wizard-type" web applications, gradually accumulating data over a sequence of pages, then, once all the data is ready, writing it to the persistent storage (this is just an example, nothing prevents of course to write to the persistent storage during intermediate steps). As I saw, the calls to a #FlowScoped bean are not synchronized, and thus there is in principle the possibility of corrupting the data stored in the bean (by doing a double submit, or launching by any other means two almost simultaneous HTTP requests, which invoke the methods of the bean). This unlike #ConversationScoped beans the calls to which are synchronized.
What puzzles me is that about #SessionScoped beans I have found several links which speak about the need to synchronize the access to a #SessionScoped bean (or recommending not to use them at all, apart from user data which changes rarely), but I have not found anything like that about #FlowScoped beans.
What is considered then to be a "best practice" for using #FlowScoped beans? Am I missing something?
EDIT
#FlowScoped seems, at least to me, to be motivated in part by Spring WebFlow, with which I have some experience, and which, as I know, offers integration with JSF 2 (not all JSF 2.2 features seem to be implemented, but it seems that PrimeFaces is usable, for example). I know that Spring WebFlow + JSF is actually used in "real world" applications, and the issue of thread safety of flow scoped objects is handled there elegantly together with double submit issues (flow execution id must be supplied with each HTTP request, and it expires and a new one is returned after a HTTP request which invokes a Spring WebFlow "action" method: therefore one cannot invoke concurrently more than one "action" method for the same user and flow id).
So I want to understand, what is the best practice in the case of JSF 2.2 if I wish to use the #FlowScoped beans to construct an application "flow" (without using Spring WebFlow). Do I really need to synchronize the access to #FlowScoped beans myself, or there is some standard way to deal with such issues?
I have a #ManagedBean #SessionScoped class to represent a user session. Assume it has a theoretical method doHorribleThings(). Access to methods of this bean through JSF can, for example, be enabled through Expression Language attributes such as action="#{userSession.doHorribleThings()}" on a Prime Faces p:commandButton.
My question is, does JSF manage access security for such method? Can a user issue performing the action of a button that is not being rendered for him, e.g. by sending an artificial HTTP package? Or does JSF capsulate a virtual client desktop that stretches accross the network, effectively enabling access control through GUI design?
No, JSF doesn't have an access security for invoking a method in a managedbean other than the UI, as far as I know.
Because if your able to mimic an action that happens through the click of a JSP/Primefaces button with a manual HTTP request then JSF container cannot identify the difference between the two and hence work the same way for both the request
We have been securing our backing bean methods using a custom #Secure interceptor to prevent forged invocations of the method.
But recently, it hit me that these methods are not reachable if the component invoking the action is not rendered. It is my understanding that JSF will generate the view, and if the component is not rendered based on permissions (e.g. EL with isUserInRole), then any forged POST with that component as the source will not fire because the component will not be found in the restored view. Is this correct?
Essentially, any forgery would have to have a compromised and current JSESSIONID and perhaps even ViewState depending on whether they needed the same view.
Can someone please confirm that my assumptions are correct and, if possible, point me to a place in the spec?
Thanks
Ok,I think I have confirmation that actions for non-rendered components are indeed not reachable according to the spec.
Section 2.2.2 of the specification states:
During the Apply Request Values phase, the JSF implementation must
call the processDecodes() method of the UIViewRoot of the component
tree.[P1-end] This will normally cause the processDecodes() method of
each component in the tree to be called recursively, as described in
the Javadocs for the UIComponent.processDecodes() method.
It also states:
During the decoding of request values, some components perform special
processing, including: Components that implement ActionSource (such as
UICommand), which recognize that they were activated, will queue an
ActionEvent. The event will be delivered at the end of Apply Request
Values phase if the immediate property of the component is true, or at
the end of Invoke Application phase if it is false.
So ActionSource components will only queue an action if they are processed according to processDecodes. Looking at the javadoc for that:
Perform the component tree processing required by the Apply Request
Values phase of the request processing lifecycle for all facets of
this component, all children of this component, and this component
itself, as follows.
If the rendered property of this UIComponent is false, skip further
processing.
So the first check must be whether or not the component is rendered, and if not, skip the rest. The ActionSource is never queued and the action never invoked.
One more note, it does appear that ViewState is only reliable for CSFR prevention as of JSF 2.2 per the spec:
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-869
Previous implementations were apparently too predictable and didn't cover GET requests. The spec now requires this.
So, while it may still be a good practice to secure the server side as well, it does appear it is sufficient to control rendering of the ActionSource component.
JSESSIONID is definitely needed. but that can be easily accessed if a user logged in - I am talking about a case when the user is logged in, but supposedly doesn't have access to the specific method.
The other part is more tricky. If the state is stored on client side, then that can be forged. Beside, there is mechanisms to provide direct link to the actions and pages - like pretty or simple link. If the method is exposed in any of those ways, it should be restricted.
I would secure them to prevent future headaches of constantly monitoring which method is exposed in what way - just imagine if you wanted to add a REST or SOA interface for the application.