springsecurity4 - Thymeleaf+Spring: ¿Cómo mantener el salto de línea?
thymeleaf-extras-spring security 5 (5)
Estoy usando el motor de plantillas Thymeleaf con Spring y me gustaría mostrar el texto almacenado a través de un área de texto multilínea.
En mi base de datos, las cadenas multilínea se almacenan con "/ n" como esto: "Test1 / nTest2 / n ...."
Con th: text tengo: "Test1 Test2" sin saltos de línea.
¿Cómo puedo mostrar el salto de línea usando Thymeleaf y evitar el reemplazo "/ n" manual con <br /> y luego evitar el uso de th: utext (esta forma abierta a la inyección xss)?
Gracias !
Debe utilizar th: utext y anexar la línea de ruptura a la cadena. Mi código es:
StringBuilder message = new StringBuilder();
message.append("some text");
message.append("<br>");
message.append("some text");
<span th:utext="${message}"></span>
Dos de tus opciones:
- Utilice th: utext: opción de configuración fácil, pero más difícil de leer y recordar
- Cree un procesador y dialecto personalizados: configuración más complicada, pero uso más fácil y legible en el futuro.
Opción 1:
Puede usar th: utext si escapa el texto usando el método de la utilidad de expresión #strings.escapeXml( text )
para evitar la inyección XSS y el formato no deseado - http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#strings
Para que esta plataforma sea independiente, puede usar T(java.lang.System).getProperty(''line.separator'')
para capturar el separador de línea.
Usando las utilidades de expresión de Thymeleaf existentes, esto funciona:
<p th:utext="${#strings.replace( #strings.escapeXml( text ),T(java.lang.System).getProperty(''line.separator''),''<br />'')}" ></p>
Opcion 2:
La API para esto ahora es diferente en 3 (escribí este tutorial para 2.1) Esperamos que pueda combinar la lógica de abajo con su tutorial oficial. Un día tal vez tenga un minuto para actualizar esto completamente. Pero por ahora: aquí está el tutorial oficial de Thymeleaf para crear tu propio dialecto.
Una vez que se complete la configuración, todo lo que deberá hacer para lograr la salida de línea de texto escapada con saltos de línea preservados:
<p fd:lstext="${ text }"></p>
La pieza principal que hace el trabajo es el procesador. El siguiente código hará el truco:
package com.foo.bar.thymeleaf.processors
import java.util.Collections;
import java.util.List;
import org.thymeleaf.Arguments;
import org.thymeleaf.Configuration;
import org.thymeleaf.dom.Element;
import org.thymeleaf.dom.Node;
import org.thymeleaf.dom.Text;
import org.thymeleaf.processor.attr.AbstractChildrenModifierAttrProcessor;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressions;
import org.unbescape.html.HtmlEscape;
public class HtmlEscapedWithLineSeparatorsProcessor extends
AbstractChildrenModifierAttrProcessor{
public HtmlEscapedWithLineSeparatorsProcessor(){
//only executes this processor for the attribute ''lstext''
super("lstext");
}
protected String getText( final Arguments arguments, final Element element,
final String attributeName) {
final Configuration configuration = arguments.getConfiguration();
final IStandardExpressionParser parser =
StandardExpressions.getExpressionParser(configuration);
final String attributeValue = element.getAttributeValue(attributeName);
final IStandardExpression expression =
parser.parseExpression(configuration, arguments, attributeValue);
final String value = (String) expression.execute(configuration, arguments);
//return the escaped text with the line separator replaced with <br />
return HtmlEscape.escapeHtml4Xml( value ).replace( System.getProperty("line.separator"), "<br />" );
}
@Override
protected final List<Node> getModifiedChildren(
final Arguments arguments, final Element element, final String attributeName) {
final String text = getText(arguments, element, attributeName);
//Create new text node signifying that content is already escaped.
final Text newNode = new Text(text == null? "" : text, null, null, true);
// Setting this allows avoiding text inliners processing already generated text,
// which in turn avoids code injection.
newNode.setProcessable( false );
return Collections.singletonList((Node)newNode);
}
@Override
public int getPrecedence() {
// A value of 10000 is higher than any attribute in the SpringStandard dialect. So this attribute will execute after all other attributes from that dialect, if in the same tag.
return 11400;
}
}
Ahora que tiene el procesador, necesita un dialecto personalizado para agregar el procesador.
package com.foo.bar.thymeleaf.dialects;
import java.util.HashSet;
import java.util.Set;
import org.thymeleaf.dialect.AbstractDialect;
import org.thymeleaf.processor.IProcessor;
import com.foo.bar.thymeleaf.processors.HtmlEscapedWithLineSeparatorsProcessor;
public class FooDialect extends AbstractDialect{
public FooDialect(){
super();
}
//This is what all the dialect''s attributes/tags will start with. So like.. fd:lstext="Hi David!<br />This is so much easier..."
public String getPrefix(){
return "fd";
}
//The processors.
@Override
public Set<IProcessor> getProcessors(){
final Set<IProcessor> processors = new HashSet<IProcessor>();
processors.add( new HtmlEscapedWithLineSeparatorsProcessor() );
return processors;
}
}
Ahora necesita agregarlo a su configuración xml o java:
Si está escribiendo una aplicación Spring MVC, solo tiene que establecerla en la propiedad adicionalDialects del bean Template Engine, para que se agregue al dialecto predeterminado de SpringStandard:
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="com.foo.bar.thymeleaf.dialects.FooDialect"/>
</set>
</property>
</bean>
O si está utilizando Spring y prefiere usar JavaConfig, puede crear una clase anotada con @Configuration en su paquete base que contenga el dialecto como un bean administrado:
package com.foo.bar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.foo.bar.thymeleaf.dialects.FooDialect;
@Configuration
public class TemplatingConfig {
@Bean
public FooDialect fooDialect(){
return new FooDialect();
}
}
Aquí hay algunas referencias adicionales sobre la creación de procesadores y dialectos personalizados: http://www.thymeleaf.org/doc/articles/sayhelloextendingthymeleaf5minutes.html , http://www.thymeleaf.org/doc/articles/sayhelloagainextendingthymeleafevenmore5minutes.html y http://www.thymeleaf.org/doc/tutorials/2.1/extendingthymeleaf.html
En mi caso, escapeJava()
devuelve valores Unicode para los símbolos cirílicos, así que envuelvo toda la ayuda del método unescapeJava()
para resolver mi problema.
<div class="text" th:utext="${#strings.unescapeJava(#strings.replace(#strings.escapeJava(comment.text),''/n'',''<br />''))}"></div>
Prueba esto
<p th:utext="${#strings.replace(#strings.escapeJava(description),''/n'',''<br />'')}" ></p>
Quizás no sea lo que tenía en mente el OP, pero esto funciona y evita la inyección de código:
<p data-th-utext="${#strings.replace(#strings.escapeXml(text),'' '',''<br>'')}"></p>
(Usando Thymeleaf de estilo HTML5.)