Migrate spring Form htmlEscape attribute behavior to Thymeleaf - spring

I'm currently working on a Spring MVC project where we are migrating all our jsp files to thymeleaf. I'm aware that the spring form tag has an htmlEscape attribute that will escape user input when rendering, such as when the user submits an invalid form and the user input is rendered bound to the form. An example of this:
<form:form method="post" id="someForm" modelAttribute="${commandName}" htmlEscape="true" autocomplete="off">
<div class="form-group">
<input type="text" id="username" value="<c:out value='${inputValue}'/>"/>
<input type="password" id="password" />
<input type="submit" class="btn btn-lg btn-block-sm" value="<spring:message code="header.content.close"/>" tabindex="0" />
<input type="hidden" name="_eventId" value="continue"/>
</div>
</form:form>
This fits under the umbrella of output-escaping, which is something that happens on the server side when processing a template to render.
An example of an xss attack this prevents is if the user entered
<script>alert("gotcha");</script> for the username, and some arbitrary value for the password. The form will rerender with the entered username bound to the form. The htmlEscape="true" attribute in the form tag will cause this output to be escaped to mitigate xss. So the username field will contain <script>alert("gotcha");</script> when the bound form rerenders with the error, instead of the actually entered valid html
Is there a standard way to achieve this same functionality in thymeleaf?
A few possibilities I see:
This is already built into thymeleaf.
I'm aware that the spring thymeleaf package uses unbescape to perform output escaping on some attributes, for example SpringValueTagProcessor which I believe escapes output on th:value attributes. However, I'm not sure this is equivalent, and fear there may be security holes left unfilled if this was done in a way that only partially mitigates what the spring form htmlEscape fully mitigates.
If so, please explain how this covers the same cases that htmlEscape does.
There is an existing Spring / Spring MVC solution that is flexible enough to not rely on jsp.
If so, what?
There is a common solution to this for thymeleaf which involves some modification of the template parsing engine.
If so, please explain.
Here is a brief article to give you an idea of what I mean regarding the spring form behavior. Regarding this article, it appears that setting the defaultHtmlEscape to false globally in the web.xml only overrides the default value of HtmlEscapeTag, which appears to only work for spring tags. Thus I don't think the solution can be applied to thymeleaf.
I would appreciate any direction here.

Escaping of output text is done automatically if you use th:text. In rare cases, you can use th:utext if you want to use unescaped text, but you have to be aware of the security implications. See Process thymeleaf variable as html code and not text for some more info.

I ended up getting an answer on the GitHub discussions for the Thymeleaf project here, which I will summarize and clarify:
HTML escaping is built into Thymeleaf form elements by default.
This is evidenced by th:input processor source code. Note the use of getDisplayString which performs html output escaping via org.springframework.web.util.HtmlUtils
I went through and manually checked all the uses of getDisplayString where htmlEscape is false and can verify that in these cases, the output is HTML escaped before displaying (in the case of SpringErrorTagProcessor and SpringUErrorsTagProcessor), they don't output any content to escape (SpringSelectedValueComparator returns a boolean), or the expression is a bound object (SPELVariableExpressionEvaluator).
See GitHub issue thymeleaf/thymeleaf-docs#84 for information regarding the docs being updated accordingly.

Related

Struts 2 XML form validation breaks when new element that does not need validation is added

I am facing an issue that is really hard to debug. I have a JSP page that has some form elements on it that submit to a Struts2 action. I also have a XML form validation file to perform some validation on the submitted fields. The file has the naming convention 'actionName-validation.xml'
This works fine, but when I add a drop down box, outside of the form, the validation now fails. Instead it redirects to a blank page and my breakpoint in my action class is not hit.
Is there a way to turn on some kind of debugging or logging for the validation? Why would adding a tag outside of a form cause this to happen?
Here is the code on the JSP page:
<s:select id="dataSource" name="selectedDataSource" theme="simple" listValue="top"
headerKey="" headerValue="Choose Data" list="dataSources" size="1" />
<div id="forms">
<s:form method="post" action="MyAction" theme="simple">
<p>
<label class="input" for="name"
<span style="color:red;">*</span>
<span>Name</span><br>
<s:textfield theme="simple" name="name" maxlength="11" size="11" />
<br>
<s:fielderror theme="plain"><s:param value="'name'" /</s:fielderror></label>
</p>
<s:submit value="Create New" theme="simple" cssStyle="display: block; clear: left;"/>
</s:form>
</div>
If I remove the <s:select> tag, it works.
Any help would be greatly appreciated it.
EDIT2: I found the problem. I needed a get method for the list that is used to populate the select drop down inside the action that the form submits to.
I had one for the action that initially is called for the page, but when the validation fails and it re-loads that page from the form action class, it tries to re-populate the select drop down and needs a getter there. I feel silly for not finding that sooner. Would be nice if there were some type of logging or messaging of these types of issues.
thanks.
The error you are encountering is not a validation error (handled by the Validation Interceptor), but an error occurred when setting the parameters (raised by the Parameters Interceptor) and for which the Conversion Error Interceptor added a fieldError, which you are not seeing because
your INPUT result lands on a blank page and
you are using theme="simple" on the textfield, which forces you to add <s:fielderror fieldName="dataSource" /> to show it (or <s:fielderror /> to show them all).
Read how the INPUT result works, set your page as the INPUT page, print the errors, then you will discover the problem, that is most likely related to the fact that you've not specified a listKey attribute in your select, that is sending the description instead of the code of the datasource to selectedDataSource, which is probably an Integer.
I found the problem. I needed a get method for the list that is used to populate the select drop down inside the action that the form submits to.
I had one for the action that initially is called for the page, but when the validation fails and it re-loads that page from the form action class, it tries to re-populate the select drop down and needs a getter there. I feel silly for not finding that sooner. Would be nice if there were some type of logging or messaging of these types of issues.

Spring Form Tag removes empty placeholder attribute

While using following tag:
<form:textarea path="message" cols="20" rows="5" placeholder="${message}"/>
I realized that if "message" can't be resolved and is therefore empty it seems that spring removes the placeholder attribute completly instead of setting it to placeholder="" or something.
Is this a known behaviour of spring form tags? Or do I miss something special here?
I realized that if "message" can't be resolved and is therefore empty
it seems that spring removes the placeholder attribute completly
instead of setting it to placeholder="" or something.
I think that was the expected behaviour of HTML. It has nothing to do with spring.
Try replacing place holder with empty in HTML page to observe the same behaviour. You can try here

Dijit form stops validating when mvc Group is used in it

I have a page which uses dijit/form/Form to validate all of the form widgets in it.
Validation works correctly if I put widgets directly under the Form (tag).
Once I surround the widgets with a dojox/mvc/Group (within the form), Form validation stops completely and none of the widgets seem to validate when I call Form::validate().
Debugging the Dojo code shows that nested widgets are never considered validatable in the Form so when I surround widgets with Group they get excluded from validation.
Is there a workaround for this?
AFAICT from dijit/form/_FormMixin#_getDescendantFormWidgets() and dijit/_WidgetBase#getChildren(), the issue can be solved by adding data-dojo-mixins="dijit/_Container" to the element having data-dojo-type="dojox/mvc/Group".
Also (though I'm not sure if it meets your requirement), dojox/mvc/tests/test_mvc_new_loan-stateful.html example shows form validation solution with dojox/mvc.
Hope it helps.
Best, Akira
It seems like there is no easy way to solve this with dijit/form/Form. At the very least, it should be subclassed or monkey-patched to make it consider nested widgets.
However, it seems that dojox/form/Manager handles nested widgets properly, so I have switched to it.
Switching to Manager required some refactoring since it cannot be simply converted into an object with dom-form (dijit/form/Form can be converted).
HTML code before:
<div
id="_pg_detailForm"
data-dojo-type="dijit/form/Form"
encType="multipart/form-data"
action="" method=""
>
... form widgets (surrounded with MVC Groups...etc)
</div>
After:
<form id="_pg_detailForm">
<div
id="_pg_detailFormManager"
data-dojo-type="dojox/form/Manager"
>
... form widgets (surrounded with MVC Groups...etc)
</div>
</form>

How can I use Spring MVC "form" tag instead of my "input" tags?

What I have:
I have a generic JSP page that is used throughout my application for displaying certain entities. The code that I am interested in goes like this:
<form:form modelAttribute="object"/>
<core:forEach items="${sections}" var="section" varStatus="itemStat">
<core:forEach items="${section.fields}" var="fieldDef">
<form:input path="${fieldDef.fieldName}"/>
</core:forEach>
</core:forEach>
<form:form>
For each section, and for each field in that section, I have an input having the path fieldName, which is what I want to display from each field.
What I want:
I would like instead of the input to be a simple text, like a label.
What I have tried:
I am most certain that I can do it somehow with <form:label> but I can't really make it work. Making a <form:label path="${fieldDef.fieldName}" /> just tells the browser for which field I need the label, but doesn't get the actual value from it.
I have also tried something like ${object.fieldDef.fieldName}, but in order for this to work I would have to first analyze the value of ${fieldDef.fieldName}, which would give me the name of the column, and then do a ${object.column}, but column being a variable I haven't been able to make this work in any way.
Alternative:
An alternative would be to just make the inputs as disabled and remove the border with CSS, but that would be a dirty way and from what I saw it is also tricky for IE different versions. I am sure that I can handle it directly.
I am a little intrigued by the fact that <form:input path="..."> puts into the input what it finds corresponding to that path (same goes for other form elements), but with label it works different.
So, what I want is basically simple, but I haven't managed to find a way. If someone could shed some light, that would be great. Thanks in advance !
You could look into the spring bind tag. I haven't tried using it before but this may work for you, in place of the input tag
<spring:bind path="fieldDef.fieldName">
${status.value}
</spring:bind>
reference: http://static.springsource.org/spring/docs/1.1.5/taglib/tag/BindTag.html
Instead of
<form:input path="${fieldDef.fieldName}"/>
use
<c:out value="${fieldDef.fieldName}"/>
It would display whatever value is there instead of creating a input field. Hope this helps you. Cheers.
Using the spring form tab, one option would be to use
<form:input disabled="true" path="${fieldDef.fieldName}"/>
To further make it not look like an input you could use CSS to style it to your preference.
Some css styles you could use:
background-color:#EEEEEE;border: 0px solid;
Update:
You could look into the spring bind tag. I haven't tried using it before but this may work for you, in place of the input tag
<spring:bind path="fieldDef.fieldName">
${status.value}
</spring:bind>

spring validation: cleanest way to makeup accompanying labels of the validated input

I'm validating the input field that's bound to path. I'm using hibernate-validator 4 for this.
Now I'd like to highlight the age label so it pops out of the page (bold, red colour etc.).
However I'm wondering what the cleanest way to do this is.
<spring:hasBindErrors name="*"/> seems to be for the whole form object instead of for a specific field. Any input is appreciated.
Spring provides special jsp tags for forms, which support this task (highlighing in case of error):
For example this jsp
...
<%# taglib prefix='form' uri='http://www.springframework.org/tags/form'%>
...
<form:form method="post"
commandName="myCommand">
<form:input path="name"
cssClass="normalLayout"
cssErrorClass="normalLayout error"/>
<form:errors path="name"
cssClass="errorMessage"/>
</form:form>
...
In this case: the input field uses the css class "normalLayout" if every thing is ok, and the css classes "normalLayout" and "name" if there is a validation error for the field.
form:errors is to print the error message generated while validation.
#see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/view.html#view-jsp-formtaglib

Resources