- Introduced user registration

- Now using Spring Boot for classloading, this way local development does not need to restart the complete server
- Fixed all kinds of dependencies on the names of the lessons necessary to keep in mind during the creation of a lesson.
- Simplied loading of resources, by adding resource mappings in MvcConfig.
- Refactored plugin loading, now only one class is left for loading the lessons.
This commit is contained in:
Nanne Baars
2017-02-25 12:15:07 +01:00
parent 9b86aaba05
commit 259fd19c1b
221 changed files with 1179 additions and 1083 deletions

View File

@ -6,11 +6,12 @@ import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.SerializationUtils;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.core.serializer.DefaultSerializer;
import java.io.File;
import java.util.HashMap;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Map;
import java.util.stream.Collectors;
@ -50,7 +51,6 @@ public class UserTracker {
private final String webgoatHome;
private final String user;
private Map<String, LessonTracker> storage = new HashMap<>();
public UserTracker(final String webgoatHome, final String user) {
this.webgoatHome = webgoatHome;
@ -64,53 +64,72 @@ public class UserTracker {
* @return the optional lesson tracker
*/
public LessonTracker getLessonTracker(AbstractLesson lesson) {
return getLessonTracker(load(), lesson);
}
/**
* Returns the lesson tracker for a specific lesson if available.
*
* @param lesson the lesson
* @return the optional lesson tracker
*/
public LessonTracker getLessonTracker(Map<String, LessonTracker> storage, AbstractLesson lesson) {
LessonTracker lessonTracker = storage.get(lesson.getTitle());
if (lessonTracker == null) {
lessonTracker = new LessonTracker(lesson);
storage.put(lesson.getTitle(), lessonTracker);
save(storage);
}
return lessonTracker;
}
public void assignmentSolved(AbstractLesson lesson, String assignmentName) {
LessonTracker lessonTracker = getLessonTracker(lesson);
Map<String, LessonTracker> storage = load();
LessonTracker lessonTracker = storage.get(lesson.getTitle());
lessonTracker.incrementAttempts();
lessonTracker.assignmentSolved(assignmentName);
save();
save(storage);
}
public void assignmentFailed(AbstractLesson lesson) {
LessonTracker lessonTracker = getLessonTracker(lesson);
Map<String, LessonTracker> storage = load();
LessonTracker lessonTracker = storage.get(lesson.getTitle());
lessonTracker.incrementAttempts();
save();
save(storage);
}
public void load() {
public Map<String, LessonTracker> load() {
File file = new File(webgoatHome, user + ".progress");
if (file.exists() && file.isFile()) {
try {
this.storage = (Map<String, LessonTracker>) SerializationUtils.deserialize(FileCopyUtils.copyToByteArray(file));
DefaultDeserializer deserializer = new DefaultDeserializer(Thread.currentThread().getContextClassLoader());
return (Map<String, LessonTracker>) deserializer.deserialize(new FileInputStream(file));
} catch (Exception e) {
log.error("Unable to read the progress file, creating a new one...");
this.storage = Maps.newHashMap();
}
}
return Maps.newHashMap();
}
@SneakyThrows
private void save() {
private void save(Map<String, LessonTracker> storage) {
File file = new File(webgoatHome, user + ".progress");
FileCopyUtils.copy(SerializationUtils.serialize(this.storage), file);
DefaultSerializer serializer = new DefaultSerializer();
serializer.serialize(storage, new FileOutputStream(file));
}
public void reset(AbstractLesson al) {
getLessonTracker(al).reset();
save();
Map<String, LessonTracker> storage = load();
LessonTracker lessonTracker = getLessonTracker(storage, al);
lessonTracker.reset();
save(storage);
}
public int numberOfLessonsSolved() {
int numberOfLessonsSolved = 0;
Map<String, LessonTracker> storage = load();
for (LessonTracker lessonTracker : storage.values()) {
if (lessonTracker.isLessonSolved()) {
numberOfLessonsSolved = numberOfLessonsSolved + 1;
@ -121,6 +140,7 @@ public class UserTracker {
public int numberOfAssignmentsSolved() {
int numberOfAssignmentsSolved = 0;
Map<String, LessonTracker> storage = load();
for (LessonTracker lessonTracker : storage.values()) {
Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview();
numberOfAssignmentsSolved = lessonOverview.values().stream().filter(b -> b).collect(Collectors.counting()).intValue();

View File

@ -0,0 +1,71 @@
package org.owasp.webgoat.session;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.util.Collection;
import java.util.Collections;
/**
* @author nbaars
* @since 3/19/17.
*/
@Getter
@Entity
public class WebGoatUser implements UserDetails {
public static final String ROLE_USER = "WEBGOAT_USER";
public static final String ROLE_ADMIN = "WEBGOAT_ADMIN";
@Id
private String username;
private String password;
private String role = ROLE_USER;
@Transient
private User user;
protected WebGoatUser() {
}
public WebGoatUser(String username, String password) {
this.username = username;
this.password = password;
createUser();
}
public void createUser() {
this.user = new User(username, password, getAuthorities());
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singleton(new SimpleGrantedAuthority(getRole()));
}
@Override
public boolean isAccountNonExpired() {
return this.user.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return this.user.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return this.user.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return this.user.isEnabled();
}
}

View File

@ -3,7 +3,6 @@ package org.owasp.webgoat.session;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import java.sql.Connection;
import java.sql.SQLException;
@ -40,10 +39,9 @@ import java.sql.SQLException;
@Slf4j
public class WebSession {
private final User currentUser;
private final WebGoatUser currentUser;
private final WebgoatContext webgoatContext;
private AbstractLesson currentLesson;
private UserTracker userTracker;
/**
* Constructor for the WebSession object
@ -52,7 +50,7 @@ public class WebSession {
*/
public WebSession(WebgoatContext webgoatContext) {
this.webgoatContext = webgoatContext;
this.currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
this.currentUser = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/**