Merge pull request #99 from nbaars/master
Button to force plugin reloading #93
This commit is contained in:
commit
5adf3a45c2
@ -149,3 +149,9 @@ cp webgoat-container/target/webgoat-container-7.0-SNAPSHOT-war-exec.jar <your_to
|
|||||||
```
|
```
|
||||||
|
|
||||||
Browse to [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat) and happy hacking !
|
Browse to [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat) and happy hacking !
|
||||||
|
|
||||||
|
|
||||||
|
## Reloading plugins
|
||||||
|
|
||||||
|
If you want to reload all the plugin visit the following url: `http://localhost:8080/WebGoat/service/reloadplugins.mvc`
|
||||||
|
in a new browser tab. After reloading a message will appear and you can refresh the WebGoat browser tab.
|
1
pom.xml
1
pom.xml
@ -161,7 +161,6 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>webgoat-container</module>
|
<module>webgoat-container</module>
|
||||||
<module>webgoat-classloader</module>
|
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
|
4
webgoat-classloader/.gitignore
vendored
4
webgoat-classloader/.gitignore
vendored
@ -1,4 +0,0 @@
|
|||||||
target/
|
|
||||||
.idea/
|
|
||||||
*.iml
|
|
||||||
dependency-reduced-pom.xml
|
|
@ -1,39 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
|
|
||||||
<name>webgoat-classloader</name>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>webgoat-classloader</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
|
||||||
<artifactId>webgoat-parent</artifactId>
|
|
||||||
<version>7.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>${maven-compiler-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<source>1.7</source>
|
|
||||||
<target>1.7</target>
|
|
||||||
<encoding>ISO-8859-1</encoding>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat</groupId>
|
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
|
||||||
<version>${tomcat-catalina.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
@ -1,46 +0,0 @@
|
|||||||
package org.owasp.webgoat.classloader;
|
|
||||||
|
|
||||||
import org.apache.catalina.loader.WebappClassLoader;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classloader for Tomcat.
|
|
||||||
*
|
|
||||||
* We need to provide this classloader otherwise jsp files cannot be compiled. JspContextWrapper uses
|
|
||||||
* Thread.currentThread().getContextClassLoader() but during initialisation it loads the classloader which means
|
|
||||||
* this classloader will never pickup the plugin classes.
|
|
||||||
*
|
|
||||||
* With this loader we can add jars we load during the plugin loading and the jsp will pick it up because this is
|
|
||||||
* the same classloader.
|
|
||||||
*
|
|
||||||
* @version $Id: $Id
|
|
||||||
*/
|
|
||||||
public class PluginClassLoader extends WebappClassLoader {
|
|
||||||
/**
|
|
||||||
* <p>Constructor for PluginClassLoader.</p>
|
|
||||||
*/
|
|
||||||
public PluginClassLoader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Constructor for PluginClassLoader.</p>
|
|
||||||
*
|
|
||||||
* @param parent a {@link java.lang.ClassLoader} object.
|
|
||||||
*/
|
|
||||||
public PluginClassLoader(ClassLoader parent) {
|
|
||||||
super(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>addURL.</p>
|
|
||||||
*
|
|
||||||
* @param urls a {@link java.util.List} object.
|
|
||||||
*/
|
|
||||||
public void addURL(List<URL> urls) {
|
|
||||||
for (URL url : urls) {
|
|
||||||
super.addURL(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -39,11 +39,6 @@
|
|||||||
<contextFile>${project.basedir}/src/main/webapp/WEB-INF/context.xml</contextFile>
|
<contextFile>${project.basedir}/src/main/webapp/WEB-INF/context.xml</contextFile>
|
||||||
</configuration>
|
</configuration>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
|
||||||
<artifactId>webgoat-classloader</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
<artifactId>webgoat-container</artifactId>
|
<artifactId>webgoat-container</artifactId>
|
||||||
@ -57,15 +52,6 @@
|
|||||||
<goal>exec-war-only</goal>
|
<goal>exec-war-only</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
<configuration>
|
|
||||||
<extraDependencies>
|
|
||||||
<extraDependency>
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
|
||||||
<artifactId>webgoat-classloader</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</extraDependency>
|
|
||||||
</extraDependencies>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>tomcat-startup</id>
|
<id>tomcat-startup</id>
|
||||||
@ -195,11 +181,6 @@
|
|||||||
<contextFile>${project.basedir}/src/main/webapp/WEB-INF/context.xml</contextFile>
|
<contextFile>${project.basedir}/src/main/webapp/WEB-INF/context.xml</contextFile>
|
||||||
</configuration>
|
</configuration>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
|
||||||
<artifactId>webgoat-classloader</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
<artifactId>webgoat-container</artifactId>
|
<artifactId>webgoat-container</artifactId>
|
||||||
@ -213,15 +194,6 @@
|
|||||||
<goal>exec-war-only</goal>
|
<goal>exec-war-only</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
<configuration>
|
|
||||||
<extraDependencies>
|
|
||||||
<extraDependency>
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
|
||||||
<artifactId>webgoat-classloader</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</extraDependency>
|
|
||||||
</extraDependencies>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -239,11 +211,6 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
|
||||||
<artifactId>webgoat-classloader</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.activation</groupId>
|
<groupId>javax.activation</groupId>
|
||||||
<artifactId>activation</artifactId>
|
<artifactId>activation</artifactId>
|
||||||
|
@ -1032,4 +1032,5 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
|||||||
return new File(w.getContext().getRealPath("/plugin_extracted/plugin/" + getLessonName() + "/"));
|
return new File(w.getContext().getRealPath("/plugin_extracted/plugin/" + getLessonName() + "/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ package org.owasp.webgoat.plugins;
|
|||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.owasp.webgoat.classloader.PluginClassLoader;
|
|
||||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -42,10 +42,11 @@ public class Plugin {
|
|||||||
|
|
||||||
private void findLesson(String name) {
|
private void findLesson(String name) {
|
||||||
String realClassName = StringUtils.trimLeadingCharacter(name, '/').replaceAll("/", ".").replaceAll(".class", "");
|
String realClassName = StringUtils.trimLeadingCharacter(name, '/').replaceAll("/", ".").replaceAll(".class", "");
|
||||||
PluginClassLoader cl = (PluginClassLoader) Thread.currentThread().getContextClassLoader();
|
//TODO should be passed in (refactor)
|
||||||
|
URLClassLoader cl = (URLClassLoader) Thread.currentThread().getContextClassLoader();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class clazz = cl.loadClass(realClassName, true);
|
Class clazz = cl.loadClass(realClassName);
|
||||||
|
|
||||||
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
||||||
this.lesson = clazz;
|
this.lesson = clazz;
|
||||||
@ -55,7 +56,7 @@ public class Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadFiles(Path file, boolean reload) {
|
public void loadFiles(Path file) {
|
||||||
if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_SOLUTION_DIRECTORY)) {
|
if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_SOLUTION_DIRECTORY)) {
|
||||||
solutionLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile());
|
solutionLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile());
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,8 @@ package org.owasp.webgoat.plugins;
|
|||||||
import javax.servlet.ServletContextEvent;
|
import javax.servlet.ServletContextEvent;
|
||||||
import javax.servlet.ServletContextListener;
|
import javax.servlet.ServletContextListener;
|
||||||
import javax.servlet.annotation.WebListener;
|
import javax.servlet.annotation.WebListener;
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@WebListener
|
@WebListener
|
||||||
/**
|
/**
|
||||||
@ -25,7 +23,7 @@ public class PluginBackgroundLoader implements ServletContextListener {
|
|||||||
String targetPath = event.getServletContext().getRealPath("plugin_extracted");
|
String targetPath = event.getServletContext().getRealPath("plugin_extracted");
|
||||||
|
|
||||||
scheduler = Executors.newSingleThreadScheduledExecutor();
|
scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
scheduler.scheduleAtFixedRate(new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)), 10, 5, TimeUnit.MINUTES);
|
//scheduler.scheduleAtFixedRate(new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)), 10, 5, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
|
@ -55,7 +55,7 @@ public class PluginExtractor {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
final File targetFile = new File(targetDirectory, zipEntry.getName());
|
final File targetFile = new File(targetDirectory, zipEntry.getName());
|
||||||
copyFile(zipFile, zipEntry, targetFile, false);
|
copyFile(zipFile, zipEntry, targetFile, false);
|
||||||
plugin.loadFiles(targetFile.toPath(), true);
|
plugin.loadFiles(targetFile.toPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean processPropertyFile(ZipFile zipFile, ZipEntry zipEntry, File targetDirectory)
|
private boolean processPropertyFile(ZipFile zipFile, ZipEntry zipEntry, File targetDirectory)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package org.owasp.webgoat.plugins;
|
package org.owasp.webgoat.plugins;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.owasp.webgoat.classloader.PluginClassLoader;
|
import org.owasp.webgoat.plugins.classloader.PluginClassLoaderFactory;
|
||||||
|
import org.owasp.webgoat.plugins.classloader.PluginClassLoaderRepository;
|
||||||
import org.owasp.webgoat.util.LabelProvider;
|
import org.owasp.webgoat.util.LabelProvider;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -11,12 +11,14 @@ import org.springframework.util.ResourceUtils;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.nio.file.FileVisitResult;
|
import java.nio.file.FileVisitResult;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CompletionService;
|
import java.util.concurrent.CompletionService;
|
||||||
import java.util.concurrent.ExecutorCompletionService;
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
@ -30,25 +32,22 @@ import java.util.concurrent.Executors;
|
|||||||
*/
|
*/
|
||||||
public class PluginsLoader implements Runnable {
|
public class PluginsLoader implements Runnable {
|
||||||
|
|
||||||
/** Constant <code>WEBGOAT_PLUGIN_EXTENSION="jar"</code> */
|
private static final String WEBGOAT_PLUGIN_EXTENSION = "jar";
|
||||||
protected static final String WEBGOAT_PLUGIN_EXTENSION = "jar";
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
private final Path pluginSource;
|
private final Path pluginSource;
|
||||||
|
private final PluginClassLoaderRepository repository;
|
||||||
private Path pluginTarget;
|
private Path pluginTarget;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Constructor for PluginsLoader.</p>
|
* <p>Constructor for PluginsLoader.</p>
|
||||||
*
|
*
|
||||||
* @param pluginSource a {@link java.nio.file.Path} object.
|
* @param pluginSource a {@link java.nio.file.Path} object.
|
||||||
* @param pluginTarget a {@link java.nio.file.Path} object.
|
* @param pluginTarget a {@link java.nio.file.Path} object.
|
||||||
*/
|
*/
|
||||||
public PluginsLoader(Path pluginSource, Path pluginTarget) {
|
public PluginsLoader(PluginClassLoaderRepository repository, Path pluginSource, Path pluginTarget) {
|
||||||
Preconditions.checkNotNull(pluginSource, "plugin source cannot be null");
|
this.pluginSource = Objects.requireNonNull(pluginSource, "plugin source cannot be null");
|
||||||
Preconditions.checkNotNull(pluginTarget, "plugin target cannot be null");
|
this.pluginTarget = Objects.requireNonNull(pluginTarget, "plugin target cannot be null");
|
||||||
|
this.repository = Objects.requireNonNull(repository, "repository cannot be null");
|
||||||
this.pluginSource = pluginSource;
|
|
||||||
this.pluginTarget = pluginTarget;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,21 +57,26 @@ public class PluginsLoader implements Runnable {
|
|||||||
* @return a {@link java.util.List} object.
|
* @return a {@link java.util.List} object.
|
||||||
*/
|
*/
|
||||||
public List<Plugin> loadPlugins(final boolean reload) {
|
public List<Plugin> loadPlugins(final boolean reload) {
|
||||||
final PluginClassLoader cl = (PluginClassLoader) Thread.currentThread().getContextClassLoader();
|
|
||||||
List<Plugin> plugins = Lists.newArrayList();
|
List<Plugin> plugins = Lists.newArrayList();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PluginFileUtils.createDirsIfNotExists(pluginTarget);
|
PluginFileUtils.createDirsIfNotExists(pluginTarget);
|
||||||
cleanupExtractedPluginsDirectory();
|
cleanupExtractedPluginsDirectory();
|
||||||
List<URL> jars = listJars();
|
List<URL> jars = listJars();
|
||||||
cl.addURL(jars);
|
initClassLoader(jars);
|
||||||
plugins = processPlugins(jars, reload);
|
plugins = processPlugins(jars);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Loading plugins failed", e);
|
logger.error("Loading plugins failed", e);
|
||||||
}
|
}
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initClassLoader(List<URL> jars) {
|
||||||
|
URLClassLoader classLoader = PluginClassLoaderFactory.createClassLoader(jars);
|
||||||
|
this.repository.replaceClassLoader(classLoader);
|
||||||
|
Thread.currentThread().setContextClassLoader(classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
private void cleanupExtractedPluginsDirectory() {
|
private void cleanupExtractedPluginsDirectory() {
|
||||||
Path i18nDirectory = pluginTarget.resolve("plugin/i18n/");
|
Path i18nDirectory = pluginTarget.resolve("plugin/i18n/");
|
||||||
FileUtils.deleteQuietly(i18nDirectory.toFile());
|
FileUtils.deleteQuietly(i18nDirectory.toFile());
|
||||||
@ -93,7 +97,7 @@ public class PluginsLoader implements Runnable {
|
|||||||
return jars;
|
return jars;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Plugin> processPlugins(List<URL> jars, boolean reload) throws Exception {
|
private List<Plugin> processPlugins(List<URL> jars) throws Exception {
|
||||||
final List<Plugin> plugins = Lists.newArrayList();
|
final List<Plugin> plugins = Lists.newArrayList();
|
||||||
final ExecutorService executorService = Executors.newFixedThreadPool(10);
|
final ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||||
final CompletionService<Plugin> completionService = new ExecutorCompletionService<>(executorService);
|
final CompletionService<Plugin> completionService = new ExecutorCompletionService<>(executorService);
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.owasp.webgoat.plugins.classloader;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a classloader for the plugins
|
||||||
|
*/
|
||||||
|
public class PluginClassLoaderFactory {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PluginClassLoaderFactory.class);
|
||||||
|
|
||||||
|
public static URLClassLoader createClassLoader(List<URL> urls) {
|
||||||
|
return new URLClassLoader(urls.toArray(new URL[urls.size()]), determineParentClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClassLoader determineParentClassLoader() {
|
||||||
|
ClassLoader parent = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
parent = Thread.currentThread().getContextClassLoader().getParent()
|
||||||
|
.loadClass("org.apache.jasper.runtime.JspContextWrapper").getClassLoader();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
logger.info("Tomcat JspContextWrapper not found, probably not running on Tomcat...");
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.owasp.webgoat.plugins.classloader;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the classloaders for the plugins. For now all the plugins are loaded by the same
|
||||||
|
* classloader. This class can be extended to contain a classloader per plugin.
|
||||||
|
*/
|
||||||
|
public class PluginClassLoaderRepository {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PluginClassLoaderRepository.class);
|
||||||
|
private URLClassLoader currentPluginLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the plugin classloader
|
||||||
|
*/
|
||||||
|
public URLClassLoader get() {
|
||||||
|
return currentPluginLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceClassLoader(URLClassLoader classLoader) {
|
||||||
|
if (this.currentPluginLoader != null) {
|
||||||
|
try {
|
||||||
|
this.currentPluginLoader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Unable to close the current classloader", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.currentPluginLoader = classLoader;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* *************************************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This file is part of WebGoat, an Open Web Application Security Project
|
||||||
|
* utility. For details, please see http://www.owasp.org/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Getting Source ==============
|
||||||
|
*
|
||||||
|
* Source for this application is maintained at
|
||||||
|
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
|
*
|
||||||
|
* For details, please see http://webgoat.github.io
|
||||||
|
*/
|
||||||
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
|
import org.owasp.webgoat.session.WebSession;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>PluginReloadService class.</p>
|
||||||
|
*
|
||||||
|
* @author nbaars
|
||||||
|
* @version $Id: $Id
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class PluginReloadService extends BaseService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PluginReloadService.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload all the plugins
|
||||||
|
*
|
||||||
|
* @param session a {@link HttpSession} object.
|
||||||
|
*/
|
||||||
|
@RequestMapping(value = "/reloadplugins.mvc")
|
||||||
|
public @ResponseBody
|
||||||
|
ResponseEntity<String> reloadPlugins(HttpSession session) {
|
||||||
|
WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION);
|
||||||
|
webSession.getCourse().loadLessonFromPlugin(session.getServletContext());
|
||||||
|
return new ResponseEntity("Plugins reload refresh the WebGoat page!",HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import org.owasp.webgoat.lessons.AbstractLesson;
|
|||||||
import org.owasp.webgoat.lessons.Category;
|
import org.owasp.webgoat.lessons.Category;
|
||||||
import org.owasp.webgoat.plugins.Plugin;
|
import org.owasp.webgoat.plugins.Plugin;
|
||||||
import org.owasp.webgoat.plugins.PluginsLoader;
|
import org.owasp.webgoat.plugins.PluginsLoader;
|
||||||
|
import org.owasp.webgoat.plugins.classloader.PluginClassLoaderRepository;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -65,14 +66,13 @@ public class Course {
|
|||||||
|
|
||||||
final Logger logger = LoggerFactory.getLogger(Course.class);
|
final Logger logger = LoggerFactory.getLogger(Course.class);
|
||||||
|
|
||||||
|
private final PluginClassLoaderRepository repository = new PluginClassLoaderRepository();
|
||||||
private final List<AbstractLesson> lessons = new LinkedList<AbstractLesson>();
|
private final List<AbstractLesson> lessons = new LinkedList<AbstractLesson>();
|
||||||
|
|
||||||
private final static String PROPERTIES_FILENAME = HammerHead.propertiesPath;
|
private final static String PROPERTIES_FILENAME = HammerHead.propertiesPath;
|
||||||
|
|
||||||
private WebgoatProperties properties = null;
|
private WebgoatProperties properties = null;
|
||||||
|
|
||||||
private final List<String> files = new LinkedList<String>();
|
|
||||||
|
|
||||||
private WebgoatContext webgoatContext;
|
private WebgoatContext webgoatContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,7 +327,7 @@ public class Course {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadLessonFromPlugin(ServletContext context) {
|
public void loadLessonFromPlugin(ServletContext context) {
|
||||||
logger.debug("Loading plugins into cache");
|
logger.debug("Loading plugins into cache");
|
||||||
String pluginPath = context.getRealPath("plugin_lessons");
|
String pluginPath = context.getRealPath("plugin_lessons");
|
||||||
String targetPath = context.getRealPath("plugin_extracted");
|
String targetPath = context.getRealPath("plugin_extracted");
|
||||||
@ -336,8 +336,8 @@ public class Course {
|
|||||||
logger.error("Plugins directory {} not found", pluginPath);
|
logger.error("Plugins directory {} not found", pluginPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
lessons.clear();
|
||||||
List<Plugin> plugins = new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins(true);
|
List<Plugin> plugins = new PluginsLoader(repository, Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins(true);
|
||||||
for (Plugin plugin : plugins) {
|
for (Plugin plugin : plugins) {
|
||||||
try {
|
try {
|
||||||
AbstractLesson lesson = plugin.getLesson().get();
|
AbstractLesson lesson = plugin.getLesson().get();
|
||||||
@ -376,5 +376,4 @@ public class Course {
|
|||||||
LegacyLoader loader = new LegacyLoader();
|
LegacyLoader loader = new LegacyLoader();
|
||||||
lessons.addAll(loader.loadLessons(webgoatContext, context, path, properties));
|
lessons.addAll(loader.loadLessons(webgoatContext, context, path, properties));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package org.owasp.webgoat.session;
|
package org.owasp.webgoat.session;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.owasp.webgoat.HammerHead;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *************************************************************************************************
|
* *************************************************************************************************
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Context antiJARLocking="true" path="/WebGoat">
|
<Context antiJARLocking="true" path="/WebGoat">
|
||||||
<Loader delegate="true" loaderClass="org.owasp.webgoat.classloader.PluginClassLoader" searchExternalFirst="true"/>
|
|
||||||
</Context>
|
</Context>
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Context antiJARLocking="true" path="/WebGoat">
|
<Context antiJARLocking="true" path="/WebGoat"/>
|
||||||
<Loader delegate="true" loaderClass="org.owasp.webgoat.classloader.PluginClassLoader" searchExternalFirst="true"/>
|
|
||||||
</Context>
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user