Provide Server-side service to support UI localization #265

- Now also enabled for adoc
This commit is contained in:
Nanne Baars 2017-02-07 21:54:34 +01:00 committed by Nanne Baars
parent 0de569339c
commit 2d6235e4f0
9 changed files with 122 additions and 54 deletions

View File

@ -1,6 +1,6 @@
/**
*************************************************************************************************
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
@ -25,28 +25,26 @@
* <p>
*
* @author WebGoat
* @since December 12, 2015
* @version $Id: $Id
* @since December 12, 2015
*/
package org.owasp.webgoat;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.asciidoctor.Asciidoctor;
import org.owasp.webgoat.i18n.Language;
import org.springframework.util.StringUtils;
import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.templateresolver.TemplateResolver;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import static org.asciidoctor.Asciidoctor.Factory.create;
@ -62,9 +60,12 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
private static final Asciidoctor asciidoctor = create();
private static final String PREFIX = "doc:";
private final File pluginTargetDirectory;
private final Language language;
public AsciiDoctorTemplateResolver(File pluginTargetDirectory) {
public AsciiDoctorTemplateResolver(File pluginTargetDirectory, Language language) {
this.pluginTargetDirectory = pluginTargetDirectory;
this.language = language;
setResourceResolver(new AdocResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
}
@ -80,7 +81,7 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
try {
Optional<Path> adocFile = find(pluginTargetDirectory.toPath(), resourceName);
Optional<Path> adocFile = resolveAdocFile(resourceName);
if (adocFile.isPresent()) {
try (FileReader reader = new FileReader(adocFile.get().toFile())) {
StringWriter writer = new StringWriter();
@ -93,6 +94,18 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
//no html yet
return new ByteArrayInputStream(new byte[0]);
}
}
private Optional<Path> resolveAdocFile(String resourceName) throws IOException {
Optional<Path> path = Optional.empty();
if (language.getLocale() != null) {
path = find(pluginTargetDirectory.toPath(), resourceName, language.getLocale().toString());
}
if (!path.isPresent()) {
path = find(pluginTargetDirectory.toPath(), resourceName, null);
}
return path;
}
private Map<String, Object> createAttributes() {
@ -106,10 +119,12 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
return options;
}
private Optional<Path> find(Path path, String resourceName) throws IOException {
private Optional<Path> find(Path path, String resourceName, String language) throws IOException {
Predicate<Path> languageFilter = p -> StringUtils.hasText(language) ? p.getParent().getFileName().toString().equals(language) : true;
return Files.walk(path)
.filter(Files::isRegularFile)
.filter(p -> p.toString().endsWith(resourceName)).findFirst();
.filter(p -> p.toString().endsWith(resourceName))
.filter(languageFilter).findFirst();
}
@Override
@ -117,4 +132,5 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
return "adocResourceResolver";
}
}
}

View File

@ -31,6 +31,7 @@
package org.owasp.webgoat;
import com.google.common.collect.Sets;
import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.i18n.Messages;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.Course;
@ -89,8 +90,8 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
}
@Bean
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver() {
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(pluginTargetDirectory);
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) {
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(pluginTargetDirectory, language);
resolver.setCacheable(true);
resolver.setOrder(3);
return resolver;
@ -118,13 +119,18 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
}
@Bean
public PluginMessages pluginMessages(Messages messages) {
return new PluginMessages(messages);
public PluginMessages pluginMessages(Messages messages, Language language) {
return new PluginMessages(messages, language);
}
@Bean
public Messages messageSource(LocaleResolver localeResolver) {
Messages messages = new Messages(localeResolver);
public Language language(LocaleResolver localeResolver) {
return new Language(localeResolver);
}
@Bean
public Messages messageSource(Language language) {
Messages messages = new Messages(language);
messages.setBasename("classpath:/i18n/messages");
return messages;
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/
package org.owasp.webgoat.i18n;
import lombok.AllArgsConstructor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.LocaleResolver;
import java.util.Locale;
/**
* Wrapper around the LocaleResolver from Spring so we do not need to bother with passing the HttpRequest object
* when asking for a Locale.
*
* @author nbaars
* @date 2/7/17
*/
@AllArgsConstructor
public class Language {
private final LocaleResolver localeResolver;
public Locale getLocale() {
return localeResolver.resolveLocale(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
}
}

View File

@ -26,11 +26,7 @@ package org.owasp.webgoat.i18n;
import lombok.AllArgsConstructor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.LocaleResolver;
import java.util.Locale;
import java.util.Properties;
/**
@ -42,7 +38,7 @@ import java.util.Properties;
@AllArgsConstructor
public class Messages extends ReloadableResourceBundleMessageSource {
private final LocaleResolver localeResolver;
private final Language language;
/**
* Gets all messages for presented Locale.
@ -50,21 +46,14 @@ public class Messages extends ReloadableResourceBundleMessageSource {
* @return all messages
*/
public Properties getMessages() {
return getMergedProperties(resolveLocale()).getProperties();
return getMergedProperties(language.getLocale()).getProperties();
}
public String getMessage(String code, Object... args) {
return getMessage(code, args, resolveLocale());
return getMessage(code, args, language.getLocale());
}
public String getMessage(String code, String defaultValue, Object... args) {
return super.getMessage(code, args, defaultValue, resolveLocale());
return super.getMessage(code, args, defaultValue, language.getLocale());
}
protected Locale resolveLocale() {
return localeResolver.resolveLocale(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
}
}

View File

@ -43,23 +43,23 @@ import java.util.Properties;
*/
public class PluginMessages extends ReloadableResourceBundleMessageSource {
private Messages messages;
private Language language;
public PluginMessages(Messages messages) {
this.messages = messages;
public PluginMessages(Messages messages, Language language) {
this.language = language;
this.setParentMessageSource(messages);
}
public Properties getMessages() {
return getMergedProperties(messages.resolveLocale()).getProperties();
return getMergedProperties(language.getLocale()).getProperties();
}
public String getMessage(String code, Object... args) {
return getMessage(code, args, messages.resolveLocale());
return getMessage(code, args, language.getLocale());
}
public String getMessage(String code, String defaultValue, Object... args) {
return super.getMessage(code, args, defaultValue, messages.resolveLocale());
return super.getMessage(code, args, defaultValue, language.getLocale());
}
public void addPluginMessageBundles(final File i18nPluginDirectory) {

View File

@ -14,6 +14,7 @@ security.enable-csrf=false
spring.devtools.restart.enabled=false
spring.resources.cache-period=0
spring.thymeleaf.cache=false
webgoat.user.directory=${user.home}/.webgoat/
webgoat.build.version=@project.version@

View File

@ -26,16 +26,15 @@
package org.owasp.webgoat.assignments;
import org.mockito.Mock;
import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.i18n.Messages;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.UserTracker;
import org.owasp.webgoat.session.WebSession;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class AssignmentEndpointTest {
@ -46,22 +45,14 @@ public class AssignmentEndpointTest {
protected WebSession webSession;
@Mock
protected UserSessionData userSessionData;
protected Messages messages = new Messages(new LocaleResolver() {
private Language language = new Language(new FixedLocaleResolver()){
@Override
public Locale resolveLocale(HttpServletRequest request) {
return Locale.ENGLISH;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}}){
@Override
protected Locale resolveLocale() {
public Locale getLocale() {
return Locale.ENGLISH;
}
};
protected PluginMessages pluginMessages = new PluginMessages(messages);
protected Messages messages = new Messages(language);
protected PluginMessages pluginMessages = new PluginMessages(messages, language);
public void init(AssignmentEndpoint a) {
messages.setBasenames("classpath:/i18n/messages", "classpath:/plugin/i18n/WebGoatLabels");

View File

@ -0,0 +1,8 @@
Voer je naam in the input field below and press "Go!" to submit. The server will accept the request, reverse the input and display it back to the user, illustrating the basics of handling an HTTP request.
The user should become familiar with the features of WebGoat by manipulating the above buttons to view hints, show the HTTP request parameters, the HTTP request cookies, and the Java source code. You may also try using OWASP ZAP Attack Proxy to see the HTTP data.
== Try It!
Enter your name in the input field below and press "Go!" to submit. The server will accept the request, reverse the input and display it back to the user, illustrating the basics of handling an HTTP request.

View File

@ -68,6 +68,12 @@
<version>4.1.3.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- Temporarily -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.7</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>