Why does JSF generate names in addition to IDs? - jsf-2

The generation / use of IDs is fairly clear, for reassociating submitted components to the view tree.
But why does JSF generate names as well? Does it use them internally?

It's required by HTML specification and used by Servlet API. Webbrowsers use input field names as HTTP request parameter names. They do not use input field IDs for that as it would otherwise be impossible to send multiple values per name (select multiple, checkbox groups, etc).
I.e.
<h:inputText id="foo">
generates
<input type="text" id="formId:foo" name="formId:foo" />
which gets in client side prepared (by webbrowser's internal code) in HTTP request as
element.getAttribute("name") + "=" + element.getAttribute("value")
and gets in server side extracted (by UIComponent#decode()) from the HTTP request as
String foo = request.getParameter(component.getClientId());
See also:
Difference between id and name attributes in HTML
How to transfer data from JSP to servlet when submitting HTML form
ServletRequest.getParameterMap() returns Map<String, String[]> and ServletRequest.getParameter() returns String?

Related

Readable data in querystring on HTTP Get

We've had a penetration test on a website and they're saying we shouldn't be passing readable data in a querystring (it's an Email Address).
The querystring is being created by the application when ModelState.isValid fails and it returns the model to the view with a HTTP GET. We are being told the EmailAddress value should be encrypted (the site is SSL).
The penetration result :
GET /Membership/RegisterMe?__RequestVerificationToken=26Oajd6AG17YkHhyZz8-pArBuKEEer7V0b86f0aR_jHXs2JqYRE8NHvhz1zCcKWtQ6eVtxtdkTvC6HjG1ami2d-2CPn8Ieedwc77fIoMB941&EmailAddress=SomeOnesEmail.com
We tried to convert the value after it's submitted by doing the following in the controller, so if validation fails it will returns an encrypted value in the querystring:-
ModelState.Remove("EmailAddress");
model.EmailAddress = Helpers.Encryption.Encrypt(model.EmailAddress);
But it loses the validation messages on the property, for example if it's an invalid email address.
Turns out using HTML Helpers in your View makes it difficult to change Model values on Postback (validation fail). It will always return the original values from the HTML helpers in the form. You can change it like so:-
ModelState.Remove("EmailAddress");
Model.EmailAddress = //new value;
My problem was I needed to keep the EmailAddress value but encrypt it before Postback, so the value is not exposed in the querystring. The above was no good as using ModelState.Remove, you also lose the Validation message (invalid Email Address etc.).
Reason was because of the HTML Helpers in the form - #Html.TextBoxFor. Changed this to
<input type="text" name="EmailAddress">
You can then change the value in the controller before postback and maintain the validation errors
Model.EmailAddress = Encrypt(Model.EmailAddress);
The postback value is encrypted and the appropriate validation error messages are displayed to the user in the View. Then did some simple code in the View to decrypt the Model.EmailAddress.

How to retrieve data-attr value of input?

I set a data-id="2" attribute on a HTML input tag. For example: <input data-id="2" value="test"/>. How do I retrieve this value in my action? I'm using dynamic text inputs where they can be sub inputs themselves.
The action can only access data which has been submitted to it (using POST or GET). If you want to be able to access the id, you'll need to grab that value using Javascript and send it with the other form data when the form is submitted.

How to pass id value to controller instead from query string while getting details of page in MVC

I want to pass insured id to controller while getting insured details which looks like:
// GET: /Insured/Details/123456789
But I don't want to pass this id number 123456789 in query string for security reasons.
Can somebody suggest me the best way. I am new to MVC.
Thanks
Try submitting the value as a hidden parameter via POST. You'll need to use a form to do POST submits though. You can't use links.
<form method="POST" action="/Insured/Details">
<input type="hidden" name="insuredid" value="123456789"/>
<input type="submit"/>
</form>
You would then get the value via request parameter. If using Java servlets, it would look something like this:
String myInsuredId = request.getParameter("insuredid");
I imagine it would look similar to other platforms as well.
NOTE: Although passing values as hidden parameters hides the data from view, this does not prevent people from sniffing the submitted data or checking the HTML source of your page. If you really want to make this secure, you'll need to use some form of encryption/security. Try looking into HTTPS posts.
You need to sanitize your input in the controller, for example if the customer is logged in you could check that the ID passed to the controller truly belongs to the customer.
Anything that is passable in request (whether it's POST or GET) is spoofable.
You should also look into serving the page over HTTPS.
E.g. (asp.net MVC / C#)
public ActionResult Details(string id)
{
if (Check(id) == false)
{
// Handle invalid input
throw new HttpException(404, "HTTP/1.1 404 Not Found");
}
// create the model
...
}

Selenium and JSF 2.0

When I a generate SelectOneMenu with JSF2.0 the the id I specified in the xhtml is attached to a generated ID from JSF.
e.g. out of my_fancy_id it generates j_idt9:my_fancy_id
Now I want to test my page with Selenium 2 Web Driver. I try to re-find my select menu:
driver.findElement(By.id("my_fancy_id"));
Of course it does't find anything because the id is changed. What is the best way to find the select menu on the page?
Usually the id of the form is prepended to all element ids inside the form. If you don't set a form id, JSF does it for you (the 'j_idt9'). Solution: Assign an id to your form and try to use the full id in your findElementmethod, e.g.:
<h:form id="myForm">
...
</h:form>
Call it this way:
driver.findElement(By.id("myForm:my_fancy_id"));
or you can add <h:form prependId="false"> so that the id of the form does not get prepended
You set the component identifier on controls; the renderers emit the client identifier to the markup.
This allows JSF to emit valid HTML ids (they must be unique) even in the face of templates and complex controls. A control will be namespaced by any parent that is a NamingContainer (such as a form).
In some containers, the client identifier will be namespaced by the view, but this generally only happens in portlet environments.
Some component libraries (like Tomahawk) have a forceId attribute, but care must be exercised in using them. I wrote a more extensive post on client identifiers here.

In Grails GSP, what is the equivalent to Spring MVC's <input name="entity.list[0].field">?

I'm coming from a Spring MVC background on a new Grails app. I have an object that contains a list of dependent objects. On the create and edit screen, I want to edit that object and its list of objects at the same time. In Spring MVC, you could use special names to bind the form fields to items in a list. Example:
Entity { String name, List items }
<form:input name="entity.items[0].value" value="${entity.items[0].value}"/>
I've tried similar variations in my GSP create and edit forms, but no luck.
I haven't used this with tag (is it a Java taglib?), but what you are doing is along the right path. I don't think you need the entity in there, the name should be just "items[0].value"
Here is some code I have that does what you need (using HTML input tag):
<input type="text" name="subItems[0].date"/>

Resources