First attempt at moving to Spring Boot 2

This commit is contained in:
Nanne Baars
2019-09-12 17:22:03 +02:00
parent a56f41e0ea
commit 361249c666
33 changed files with 271 additions and 398 deletions

View File

@ -39,12 +39,15 @@ import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
import org.owasp.webgoat.asciidoc.WebWolfMacro;
import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
import org.owasp.webgoat.i18n.Language;
import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.templateresolver.TemplateResolver;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Map;
import static org.asciidoctor.Asciidoctor.Factory.create;
@ -57,7 +60,7 @@ import static org.asciidoctor.Asciidoctor.Factory.create;
* </code>
*/
@Slf4j
public class AsciiDoctorTemplateResolver extends TemplateResolver {
public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
private static final Asciidoctor asciidoctor = create();
private static final String PREFIX = "doc:";
@ -65,72 +68,56 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
public AsciiDoctorTemplateResolver(Language language) {
this.language = language;
setResourceResolver(new AdocResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
}
@Override
protected String computeResourceName(TemplateProcessingParameters params) {
String templateName = params.getTemplateName();
return templateName.substring(PREFIX.length());
}
private class AdocResourceResolver implements IResourceResolver {
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
try (InputStream is = readInputStreamOrFallbackToEnglish(resourceName, language)) {
if (is == null) {
log.warn("Resource name: {} not found, did you add the adoc file?", resourceName);
return new ByteArrayInputStream(new byte[0]);
} else {
StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8));
}
} catch (IOException e) {
//no html yet
return new ByteArrayInputStream(new byte[0]);
}
}
/**
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
*/
private String computeResourceName(String resourceName, String language) {
return String.format("lessonPlans/%s/%s", language, resourceName);
}
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
var templateName = resourceName.substring(PREFIX.length());
try (InputStream is = readInputStreamOrFallbackToEnglish(templateName, language)) {
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en"));
log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
return new StringTemplateResource("");
} else {
StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new StringTemplateResource(writer.getBuffer().toString());
}
return is;
}
private Map<String, Object> createAttributes() {
Map<String, Object> attributes = Maps.newHashMap();
attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml");
Map<String, Object> options = Maps.newHashMap();
options.put("attributes", attributes);
return options;
}
@Override
public String getName() {
return "adocResourceResolver";
} catch (IOException e) {
//no html yet
return new StringTemplateResource("");
}
}
/**
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
*/
private String computeResourceName(String resourceName, String language) {
return String.format("lessonPlans/%s/%s", language, resourceName);
}
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en"));
}
return is;
}
private Map<String, Object> createAttributes() {
Map<String, Object> attributes = Maps.newHashMap();
attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml");
Map<String, Object> options = Maps.newHashMap();
options.put("attributes", attributes);
return options;
}
}

View File

@ -1,47 +1,46 @@
/**
*************************************************************************************************
*
*
* ************************************************************************************************
* <p>
* <p>
* 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 - 20014 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.
*
* @author WebGoat
* @since October 28, 2003
* @version $Id: $Id
* @since October 28, 2003
*/
package org.owasp.webgoat;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import lombok.SneakyThrows;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.templateresolver.TemplateResolver;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
@ -53,42 +52,29 @@ import java.util.Map;
*
* Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory
*/
public class LessonTemplateResolver extends TemplateResolver {
public class LessonTemplateResolver extends FileTemplateResolver {
private final static String PREFIX = "lesson:";
private final File pluginTargetDirectory;
private ResourceLoader resourceLoader;
private Map<String, byte[]> resources = Maps.newHashMap();
public LessonTemplateResolver(File pluginTargetDirectory, ResourceLoader resourceLoader) {
this.pluginTargetDirectory = pluginTargetDirectory;
public LessonTemplateResolver(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
setResourceResolver(new LessonResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
}
@Override
protected String computeResourceName(TemplateProcessingParameters params) {
String templateName = params.getTemplateName();
return templateName.substring(PREFIX.length());
}
private class LessonResourceResolver implements IResourceResolver {
@Override
@SneakyThrows
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
byte[] resource = resources.get(resourceName);
if (resource == null) {
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + resourceName + ".html").getInputStream());
resources.put(resourceName, resource);
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
var templateName = resourceName.substring(PREFIX.length());;
byte[] resource = resources.get(templateName);
if (resource == null) {
try {
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return new ByteArrayInputStream(resource);
}
@Override
public String getName() {
return "lessonResourceResolver";
resources.put(resourceName, resource);
}
return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
}
}
}

View File

@ -30,41 +30,38 @@
*/
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.LabelDebugger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import java.io.File;
import java.util.Set;
/**
* Configuration for Spring MVC
*/
@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
public class MvcConfiguration implements WebMvcConfigurer {
private static final String UTF8 = "UTF-8";
@Autowired
@Qualifier("pluginTargetDirectory")
private File pluginTargetDirectory;
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
@ -74,13 +71,21 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
//registry.addViewController("/list_users").setViewName("list_users");
}
@Bean
public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(thymeleafTemplateEngine);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
@Bean
public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html");
resolver.setOrder(1);
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setOrder(2);
resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8);
resolver.setApplicationContext(applicationContext);
@ -89,8 +94,8 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Bean
public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) {
LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory, resourceLoader);
resolver.setOrder(2);
LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader);
resolver.setOrder(0);
resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8);
return resolver;
@ -100,19 +105,20 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) {
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language);
resolver.setCacheable(false);
resolver.setOrder(3);
resolver.setOrder(1);
resolver.setCharacterEncoding(UTF8);
return resolver;
}
@Bean
public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver,
public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver,
LessonTemplateResolver lessonTemplateResolver,
AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.addDialect(new SpringSecurityDialect());
engine.setTemplateResolvers(
Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver));
Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, springThymeleafTemplateResolver));
return engine;
}
@ -123,12 +129,10 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/");
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/");
registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/");
registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/");
super.addResourceHandlers(registry);
}
@Bean

View File

@ -30,15 +30,11 @@
*/
package org.owasp.webgoat;
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
import org.owasp.webgoat.plugins.PluginsLoader;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
@ -66,16 +62,6 @@ public class WebGoat {
return new UserSessionData("test", "data");
}
@Bean
public PluginEndpointPublisher pluginEndpointPublisher(ApplicationContext applicationContext) {
return new PluginEndpointPublisher(applicationContext);
}
@Bean
public Course course(PluginEndpointPublisher pluginEndpointPublisher) {
return new PluginsLoader(pluginEndpointPublisher).loadPlugins();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();

View File

@ -35,6 +35,7 @@ import org.owasp.webgoat.users.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
@ -42,6 +43,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/**
* Security configuration for WebGoat.
@ -90,4 +92,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService;
}
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}

View File

@ -41,7 +41,8 @@ import org.springframework.beans.factory.annotation.Autowired;
* </p>
* Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
*/
public abstract class AssignmentEndpoint extends Endpoint {
//TODO: rename to assignment
public abstract class AssignmentEndpoint {
@Autowired
private UserTrackerRepository userTrackerRepository;
@ -76,11 +77,6 @@ public abstract class AssignmentEndpoint extends Endpoint {
return userSessionData;
}
@Override
public final String getPath() {
return this.getClass().getAnnotationsByType(AssignmentPath.class)[0].value();
}
/**
* Convenience method for create a successful result:
*

View File

@ -1,5 +1,9 @@
package org.owasp.webgoat.assignments;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -10,7 +14,15 @@ import java.lang.annotation.Target;
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
//@RequestMapping
public @interface AssignmentPath {
String value();
// @AliasFor(annotation = RequestMapping.class)
String[] path() default {};
// @AliasFor(annotation = RequestMapping.class)
RequestMethod[] method() default {};
// @AliasFor("path")
String value() default "";
}

View File

@ -1,41 +0,0 @@
/*
* 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.assignments;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
public abstract class Endpoint implements MvcEndpoint {
@Override
public final boolean isSensitive() {
return false;
}
@Override
public final Class<? extends org.springframework.boot.actuate.endpoint.Endpoint> getEndpointType() {
return null;
}
}

View File

@ -52,8 +52,8 @@ public class Assignment {
//Hibernate
}
public Assignment(String name, String path) {
this(name, path, Lists.newArrayList());
public Assignment(String name) {
this(name, name, Lists.newArrayList());
}
public Assignment(String name, String path, List<String> hints) {

View File

@ -1,66 +0,0 @@
package org.owasp.webgoat.plugins;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.Endpoint;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import java.util.List;
/**
* ************************************************************************************************
* 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 - 20014 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>
*
* @author nbaars
* @version $Id: $Id
* @since October 16, 2016
*/
@Slf4j
public class PluginEndpointPublisher {
private AbstractApplicationContext applicationContext;
public PluginEndpointPublisher(ApplicationContext applicationContext) {
this.applicationContext = (AbstractApplicationContext) applicationContext;
}
public void publish(List<Class<Endpoint>> endpoints) {
endpoints.forEach(e -> publishEndpoint(e));
}
private void publishEndpoint(Class<? extends MvcEndpoint> e) {
try {
BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
} catch (Exception ex) {
log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
}
}
}

View File

@ -3,19 +3,12 @@ package org.owasp.webgoat.plugins;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.lessons.NewLesson;
import java.net.URL;
import java.util.List;
import java.util.stream.Collectors;
/**
* Plugin resource
*
* @author nbaars
* @since 3/4/17.
*/
@AllArgsConstructor
@Getter
public class PluginResource {
@ -27,13 +20,6 @@ public class PluginResource {
return classes.stream().filter(c -> c.getSuperclass() == NewLesson.class).collect(Collectors.toList());
}
public List<Class<Endpoint>> getEndpoints() {
return classes.stream().
filter(c -> c.getSuperclass() == AssignmentEndpoint.class || c.getSuperclass() == Endpoint.class).
map(c -> (Class<Endpoint>) c).
collect(Collectors.toList());
}
public List<Class<AssignmentEndpoint>> getAssignments(Class lesson) {
return classes.stream().
filter(c -> c.getSuperclass() == AssignmentEndpoint.class).

View File

@ -8,14 +8,22 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.NewLesson;
import org.owasp.webgoat.session.Course;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;
import java.util.Map;
@ -56,13 +64,12 @@ import static java.util.stream.Collectors.toList;
*/
@AllArgsConstructor
@Slf4j
@Configuration
public class PluginsLoader {
private final PluginEndpointPublisher pluginEndpointPublisher;
/**
* <p>createLessonsFromPlugins.</p>
*/
@Bean
public Course loadPlugins() {
List<AbstractLesson> lessons = Lists.newArrayList();
for (PluginResource plugin : findPluginResources()) {
@ -70,7 +77,7 @@ public class PluginsLoader {
plugin.getLessons().forEach(c -> {
NewLesson lesson = null;
try {
lesson = (NewLesson) c.newInstance();
lesson = (NewLesson) c.getConstructor().newInstance();
log.trace("Lesson loaded: {}", lesson.getId());
} catch (Exception e) {
log.error("Error while loading:" + c, e);
@ -78,7 +85,6 @@ public class PluginsLoader {
List<Class<AssignmentEndpoint>> assignments = plugin.getAssignments(c);
lesson.setAssignments(createAssignment(assignments));
lessons.add(lesson);
pluginEndpointPublisher.publish(plugin.getEndpoints());
});
} catch (Exception e) {
log.error("Error in loadLessons: ", e);
@ -97,7 +103,29 @@ public class PluginsLoader {
}
private String getPath(Class<AssignmentEndpoint> e) {
return e.getAnnotationsByType(AssignmentPath.class)[0].value();
for (Method m : e.getMethods()) {
if (m.getReturnType() == AttackResult.class) {
var mapping = m.getAnnotation(RequestMapping.class);
if (mapping == null) {
log.error("AttackResult method found without mapping in: {}", e.getSimpleName());
} else {
return getMapping(m);
}
}
}
return "";
}
private String getMapping(Method m) {
String[] path = null;
if (m.getAnnotation(RequestMapping.class) != null) {
path = m.getAnnotation(RequestMapping.class).path();
} else if (m.getAnnotation(PostMapping.class) != null) {
path = m.getAnnotation(PostMapping.class).path();
} else if (m.getAnnotation(GetMapping.class) != null) {
path = m.getAnnotation(GetMapping.class).value();
}
return path != null && path.length > 0 ? path[0] : "";
}
private List<String> getHints(Class<AssignmentEndpoint> e) {
@ -107,8 +135,6 @@ public class PluginsLoader {
return Lists.newArrayList();
}
@SneakyThrows
public List<PluginResource> findPluginResources() {
final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);

View File

@ -76,7 +76,7 @@ public class LessonProgressService {
}
private List<LessonOverview> toJson(Map<Assignment, Boolean> map) {
ArrayList<LessonOverview> result = Lists.newArrayList();
List<LessonOverview> result = new ArrayList();
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
result.add(new LessonOverview(entry.getKey(), entry.getValue()));
}