WebGoat/java/org/owasp/webgoat/session/WebSession.java
lawson89 2d7679cdda fix various session issues and cleanup
main change is to force spring security to always send user to welcome.mvc after login which gets their session setup properly before redirecting to start.mvc
2014-08-21 09:05:12 -04:00

1045 lines
30 KiB
Java

package org.owasp.webgoat.session;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.Principal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.RandomLessonAdapter;
import org.owasp.webgoat.lessons.SequentialLessonAdapter;
import org.owasp.webgoat.lessons.model.RequestParameter;
import org.owasp.webgoat.util.WebGoatI18N;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* *************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2007 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 code.google.com, a repository
* for free software projects.
*
* For details, please see http://code.google.com/p/webgoat/
*
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect
* Security</a>
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
*
* @created October 28, 2003
*/
public class WebSession {
final Logger logger = LoggerFactory.getLogger(WebSession.class);
/**
* Description of the Field
*/
public final static String ADMIN = "admin";
/**
* Tomcat role for a webgoat user
*/
public final static String WEBGOAT_USER = "webgoat_user";
/**
* Tomcat role for a webgoat admin
*/
public final static String WEBGOAT_ADMIN = "webgoat_admin";
/**
* Description of the Field
*/
public final static String CHALLENGE = "Challenge";
/**
* Description of the Field
*/
public final static String COLOR = "color";
public final static String COURSE = "course";
/**
* Description of the Field
*/
public final static int ERROR = 0;
public static final String STAGE = "stage";
/**
* Description of the Field
*/
public final static String JSESSION_ID = "jsessionid";
/**
* Description of the Field
*/
public final static String LOGOUT = "Logout";
/**
* Description of the Field
*/
public final static String RESTART = "Restart";
/**
* Description of the Field
*/
public final static String MENU = "menu";
/**
* Description of the Field
*/
public final static String SCREEN = "Screen";
/**
* Description of the Field
*/
public final static String SESSION = "websession";
public final static String SHOWSOURCE = "ShowSource";
public final static String SHOWSOLUTION = "ShowSolution";
public final static String SHOWHINTS = "ShowHints";
public final static String SHOW = "show";
public final static String SHOW_NEXTHINT = "NextHint";
public final static String SHOW_PREVIOUSHINT = "PreviousHint";
public final static String SHOW_PARAMS = "Params";
public final static String SHOW_COOKIES = "Cookies";
public final static String SHOW_SOURCE = "Source";
public final static String SHOW_SOLUTION = "Solution";
public final static String DEBUG = "debug";
public final static String LANGUAGE = "language";
/**
* Description of the Field
*/
public final static int WELCOME = -1;
private WebgoatContext webgoatContext;
private ServletContext context = null;
private Course course;
private int currentScreen = WELCOME;
private int previousScreen = ERROR;
private int hintNum = -1;
private boolean isAdmin = false;
private boolean isHackedAdmin = false;
private boolean isAuthenticated = false;
private boolean isColor = false;
private boolean isDebug = false;
private boolean hasHackedHackableAdmin = false;
private StringBuffer message = new StringBuffer("");
private ParameterParser myParser;
private HttpServletRequest request = null;
private HttpServletResponse response = null;
private String servletName;
private HashMap<String, Object> session = new HashMap<String, Object>();
private boolean showCookies = false;
private boolean showParams = false;
private boolean showRequest = false;
private boolean showSource = false;
private boolean showSolution = false;
private boolean completedHackableAdmin = false;
private int currentMenu;
private String currentLanguage = null;
private List<Cookie> cookiesOnLastRequest;
private List<RequestParameter> parmsOnLastRequest;
/**
* Constructor for the WebSession object
*
* @param servlet Description of the Parameter
* @param context Description of the Parameter
*/
public WebSession(WebgoatContext webgoatContext, ServletContext context) {
this.webgoatContext = webgoatContext;
// initialize from web.xml
showParams = webgoatContext.isShowParams();
showCookies = webgoatContext.isShowCookies();
showSource = webgoatContext.isShowSource();
showSolution = webgoatContext.isShowSolution();
showRequest = webgoatContext.isShowRequest();
currentLanguage = webgoatContext.getDefaultLanguage();
this.context = context;
course = new Course();
course.loadCourses(webgoatContext, context, "/");
}
public static synchronized Connection getConnection(WebSession s) throws SQLException {
return DatabaseUtilities.getConnection(s);
}
public static void returnConnection(WebSession s) {
DatabaseUtilities.returnConnection(s.getUserName());
}
/**
* Description of the Method
*
* @param key Description of the Parameter
* @param value Description of the Parameter
*/
public void add(String key, Object value) {
session.put(key, value);
}
/**
* Description of the Method
*/
public void clearMessage() {
message.setLength(0);
}
/**
* Description of the Method
*/
public void eatCookies() {
Cookie[] cookies = request.getCookies();
for (int loop = 0; loop < cookies.length; loop++) {
if (!cookies[loop].getName().startsWith("JS")) {// skip jsessionid cookie
cookies[loop].setMaxAge(0);// mark for deletion by browser
response.addCookie(cookies[loop]);
}
}
}
/**
* Description of the Method
*
* @param key Description of the Parameter
* @return Description of the Return Value
*/
public Object get(String key) {
return (session.get(key));
}
/**
* Gets the context attribute of the WebSession object
*
* @return The context value
*/
public ServletContext getContext() {
return context;
}
public List<String> getRoles() {
List<String> roles = new ArrayList<String>();
roles.add(AbstractLesson.USER_ROLE);
if (isAdmin()) {
roles.add(AbstractLesson.ADMIN_ROLE);
}
return roles;
}
/**
* Sets the admin flag - this routine is ONLY here to allow someone a
* backdoor to setting the user up as an admin.
*
* This is also used by the WebSession to set the admin, but the method
* should be private
*
* @param state
*/
public void setAdmin(boolean state) {
isAdmin = state;
}
public String getRole() {
String role = "";
if (isAdmin()) {
role = AbstractLesson.ADMIN_ROLE;
} else if (isHackedAdmin()) {
role = AbstractLesson.HACKED_ADMIN_ROLE;
} else if (isChallenge()) {
role = AbstractLesson.CHALLENGE_ROLE;
} else {
role = AbstractLesson.USER_ROLE;
}
return role;
}
/**
* Gets the course attribute of the WebSession object
*
* @return The course value
*/
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
/**
* Gets the currentScreen attribute of the WebSession object
*
* @return The currentScreen value
*/
public int getCurrentScreen() {
return (currentScreen);
}
public void setCurrentScreen(int screen) {
currentScreen = screen;
}
public String getRestartLink() {
return getCurrentLesson().getLink() + "&" + RESTART + "=" + getCurrentScreen();
}
public String getCurrentLink() {
String thisLink = "attack";
Enumeration<String> e = request.getParameterNames();
boolean isFirstParameter = true;
while (e.hasMoreElements()) {
String name = e.nextElement();
if (isFirstParameter) {
isFirstParameter = false;
thisLink += "?";
} else {
thisLink += "&";
}
thisLink = thisLink + name + "=" + request.getParameter(name);
}
return thisLink;
}
public AbstractLesson getCurrentLesson() {
return getCourse().getLesson(this, getCurrentScreen(), getRoles());
}
public AbstractLesson getLesson(int id) {
return getCourse().getLesson(this, id, getRoles());
}
public List<AbstractLesson> getLessons(Category category) {
return getCourse().getLessons(this, category, getRoles());
}
/**
* Gets the hint1 attribute of the WebSession object
*
* @return The hint1 value
*/
private int getHintNum() {
return (hintNum);
}
public String getHint() {
String hint = null;
int hints = getCurrentLesson().getHintCount(this);
if (getHintNum() > hints) {
hintNum = -1;
}
if (getHintNum() >= 0) // FIXME
{
hint = getCurrentLesson().getHint(this, getHintNum());
}
return hint;
}
public List<Parameter> getParams() {
Vector<Parameter> params = null;
if (showParams() && getParser() != null) {
params = new Vector<Parameter>();
Enumeration<String> e = getParser().getParameterNames();
while ((e != null) && e.hasMoreElements()) {
String name = (String) e.nextElement();
String[] values = getParser().getParameterValues(name);
for (int loop = 0; (values != null) && (loop < values.length); loop++) {
params.add(new Parameter(name, values[loop]));
// params.add( name + " -> " + values[loop] );
}
}
Collections.sort(params);
}
return params;
}
public List<Cookie> getCookies() {
List<Cookie> cookies = null;
if (showCookies()) {
cookies = Arrays.asList(request.getCookies());
}
/*
* List cookies = new Vector(); HttpServletRequest request = getRequest(); Cookie[] cookies
* = request.getCookies(); if ( cookies.length == 0 ) { list.addElement( new LI(
* "No Cookies" ) ); } for ( int i = 0; i < cookies.length; i++ ) { Cookie cookie =
* cookies[i]; cookies.add(cookie); //list.addElement( new LI( cookie.getName() + " -> " +
* cookie.getValue() ) ); }
*/
return cookies;
}
/**
* Gets the cookie attribute of the CookieScreen object
*
* @param s Description of the Parameter
* @return The cookie value
*/
public String getCookie(String cookieName) {
Cookie[] cookies = getRequest().getCookies();
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equalsIgnoreCase(cookieName)) {
return (cookies[i].getValue());
}
}
return (null);
}
public String getSource() {
return "Sorry. No Java Source viewing available.";
// return getCurrentLesson().getSource(this);
}
public String getSolution() {
return "Sorry. No solution is available.";
// return getCurrentLesson().getSolution(this);
}
public String getInstructions() {
return getCurrentLesson().getInstructions(this);
}
/**
* Gets the message attribute of the WebSession object
*
* @return The message value
*/
public String getMessage() {
return (message.toString());
}
/**
* Gets the parser attribute of the WebSession object
*
* @return The parser value
*/
public ParameterParser getParser() {
return (myParser);
}
/**
* Gets the previousScreen attribute of the WebSession object
*
* @return The previousScreen value
*/
public int getPreviousScreen() {
return (previousScreen);
}
/**
* Gets the request attribute of the WebSession object
*
* @return The request value
*/
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
/**
* Gets the response attribute of the WebSession object
*
* @return The response value
*/
public HttpServletResponse getResponse() {
return response;
}
/**
* Gets the servletName attribute of the WebSession object
*
* @return The servletName value
*/
public String getServletName() {
return (servletName);
}
/**
* Gets the sourceFile attribute of the WebSession object
*
* @param screen Description of the Parameter
* @return The sourceFile value
*/
public String getWebResource(String fileName) {
// Note: doesn't work for admin path! Maybe with a ../ attack
return (context.getRealPath(fileName));
}
/**
* Gets the admin attribute of the WebSession object
*
* @return The admin value
*/
public boolean isAdmin() {
return (isAdmin);
}
/**
* Gets the hackedAdmin attribute of the WebSession object
*
* @return The hackedAdmin value
*/
public boolean isHackedAdmin() {
return (isHackedAdmin);
}
/**
* Has the user ever hacked the hackable admin
*
* @return The hackedAdmin value
*/
public boolean completedHackableAdmin() {
return (completedHackableAdmin);
}
/**
* Gets the authenticated attribute of the WebSession object
*
* @return The authenticated value
*/
public boolean isAuthenticated() {
return (isAuthenticated);
}
private Map<AbstractLesson, LessonSession> lessonSessions = new Hashtable<AbstractLesson, LessonSession>();
public boolean isAuthenticatedInLesson(AbstractLesson lesson) {
boolean authenticated = false;
LessonSession lessonSession = getLessonSession(lesson);
if (lessonSession != null) {
authenticated = lessonSession.isAuthenticated();
}
// System.out.println("Authenticated for lesson " + lesson + "? " + authenticated);
return authenticated;
}
public boolean isAuthorizedInLesson(int employeeId, String functionId) {
return getCurrentLesson().isAuthorized(this, employeeId, functionId);
}
public boolean isAuthorizedInLesson(String role, String functionId) {
return getCurrentLesson().isAuthorized(this, role, functionId);
}
public int getUserIdInLesson() throws ParameterNotFoundException {
return getCurrentLesson().getUserId(this);
}
public String getUserNameInLesson() throws ParameterNotFoundException {
return getCurrentLesson().getUserName(this);
}
public void openLessonSession(AbstractLesson lesson) {
System.out.println("Opening new lesson session for lesson " + lesson);
LessonSession lessonSession = new LessonSession();
lessonSessions.put(lesson, lessonSession);
}
public void closeLessonSession(AbstractLesson lesson) {
lessonSessions.remove(lesson);
}
public LessonSession getLessonSession(AbstractLesson lesson) {
return lessonSessions.get(lesson);
}
/**
* Gets the challenge attribute of the WebSession object
*
* @return The challenge value
*/
public boolean isChallenge() {
if (getCurrentLesson() != null) {
return (Category.CHALLENGE.equals(getCurrentLesson().getCategory()));
}
return false;
}
/**
* Gets the color attribute of the WebSession object
*
* @return The color value
*/
public boolean isColor() {
return (isColor);
}
/**
* Gets the screen attribute of the WebSession object
*
* @param value Description of the Parameter
* @return The screen value
*/
public boolean isScreen(int value) {
return (getCurrentScreen() == value);
}
/**
* Gets the user attribute of the WebSession object
*
* @return The user value
*/
public boolean isUser() {
return (!isAdmin && !isChallenge());
}
/**
* Sets the message attribute of the WebSession object
*
* @param text The new message value
*/
public void setMessage(String text) {
message.append("<BR>" + " * " + text);
}
public void setLineBreak(String text) {
message.append("<BR><BR>" + text);
}
/**
* Description of the Method
*
* @return Description of the Return Value
*/
public boolean showCookies() {
return (showCookies);
}
/**
* Description of the Method
*
* @return Description of the Return Value
*/
public boolean showParams() {
return (showParams);
}
/**
* Description of the Method
*
* @return Description of the Return Value
*/
public boolean showRequest() {
return (showRequest);
}
/**
* Description of the Method
*
* @return Description of the Return Value
*/
public boolean showSource() {
return (showSource);
}
public boolean showSolution() {
return (showSolution);
}
/**
* Gets the userName attribute of the WebSession object
*
* @return The userName value
*/
public String getUserName() {
HttpServletRequest request = getRequest();
if (request == null) {
throw new RuntimeException("Could not find the ServletRequest in the web session");
}
Principal principal = request.getUserPrincipal();
if (principal == null) {
throw new RuntimeException("Could not find the Principal in the Servlet Request");
}
return principal.getName();
}
/**
* Parse parameters from the given request, handle any servlet commands, and
* update this session based on the parameters.
*
* @param request Description of the Parameter
* @param response Description of the Parameter
* @param name Description of the Parameter
*/
public void update(HttpServletRequest request, HttpServletResponse response, String name) throws IOException {
String content = null;
clearMessage();
this.request = request;
this.response = response;
this.servletName = name;
if (myParser == null) {
myParser = new ParameterParser(request);
} else {
myParser.update(request);
}
if (myParser.getRawParameter(LANGUAGE, null) != null) {
this.currentLanguage = new String(myParser.getRawParameter(LANGUAGE, null));
WebGoatI18N.setCurrentLanguage(this.currentLanguage);
}
// System.out.println("Current Screen 1: " + currentScreen );
// System.out.println("Previous Screen 1: " + previousScreen );
// FIXME: requires ?Logout=true
// FIXME: doesn't work right -- no reauthentication
// REMOVED - we have explicit logout now via spriing security
/*
if (myParser.getRawParameter(LOGOUT, null) != null) {
System.out.println("Logout " + request.getUserPrincipal());
eatCookies();
request.getSession().invalidate();
currentScreen = WELCOME;
previousScreen = ERROR;
}
*/
// There are several scenarios where we want the first lesson to be loaded
// 1) Previous screen is Welcome - Start of the course
// 2) After a logout and after the session has been reinitialized
if ((this.getPreviousScreen() == WebSession.WELCOME) || (getRequest().getSession(false) != null
&& // getRequest().getSession(false).isNew() &&
this.getCurrentScreen() == WebSession.WELCOME && this.getPreviousScreen() == WebSession.ERROR)) {
currentScreen = course.getFirstLesson().getScreenId();
hintNum = -1;
}
// System.out.println("Current Screen 2: " + currentScreen );
// System.out.println("Previous Screen 2: " + previousScreen );
// update the screen variables
previousScreen = currentScreen;
try {
// If the request is new there should be no parameters.
// This can occur from a session timeout or a the starting of a new course.
if (!request.getSession().isNew()) {
currentScreen = myParser.getIntParameter(SCREEN, currentScreen);
} else {
if (!myParser.getRawParameter(SCREEN, "NULL").equals("NULL")) {
this.setMessage("Session Timeout - Starting new Session.");
}
}
} catch (Exception e) {
}
// clear variables when switching screens
if (this.getCurrentScreen() != this.getPreviousScreen()) {
if (webgoatContext.isDebug()) {
setMessage("Changed to a new screen, clearing cookies and hints");
}
eatCookies();
hintNum = -1;
} else if (myParser.getRawParameter(STAGE, null) != null) {
AbstractLesson al = getCurrentLesson();
if (al instanceof SequentialLessonAdapter) {
SequentialLessonAdapter sla = (SequentialLessonAdapter) al;
int stage = myParser.getIntParameter(STAGE, sla.getStage(this));
if (stage > 0 && stage <= sla.getStageCount()) {
sla.setStage(this, stage);
}
} else if (al instanceof RandomLessonAdapter) {
try {
RandomLessonAdapter rla = (RandomLessonAdapter) al;
int stage = myParser.getIntParameter(STAGE) - 1;
String[] stages = rla.getStages();
if (stages == null) {
stages = new String[0];
}
if (stage >= 0 && stage < stages.length) {
rla.setStage(this, stages[stage]);
}
} catch (ParameterNotFoundException pnfe) {
}
}
} // else update global variables for the current screen
else {
// Handle "restart" commands
int lessonId = myParser.getIntParameter(RESTART, -1);
if (lessonId != -1) {
restartLesson(lessonId);
}
// if ( myParser.getBooleanParameter( RESTART, false ) )
// {
// getCurrentLesson().getLessonTracker( this ).getLessonProperties().setProperty(
// CHALLENGE_STAGE, "1" );
// }
// Handle "show" commands
String showCommand = myParser.getStringParameter(SHOW, null);
if (showCommand != null) {
if (showCommand.equalsIgnoreCase(SHOW_PARAMS)) {
showParams = !showParams;
} else if (showCommand.equalsIgnoreCase(SHOW_COOKIES)) {
showCookies = !showCookies;
} else if (showCommand.equalsIgnoreCase(SHOW_SOURCE)) {
content = getSource();
// showSource = true;
} else if (showCommand.equalsIgnoreCase(SHOW_SOLUTION)) {
content = getSolution();
// showSource = true;
} else if (showCommand.equalsIgnoreCase(SHOW_NEXTHINT)) {
getNextHint();
} else if (showCommand.equalsIgnoreCase(SHOW_PREVIOUSHINT)) {
getPreviousHint();
}
}
}
isAdmin = request.isUserInRole(WEBGOAT_ADMIN);
isHackedAdmin = myParser.getBooleanParameter(ADMIN, isAdmin);
if (isHackedAdmin) {
System.out.println("Hacked admin");
hasHackedHackableAdmin = true;
}
isColor = myParser.getBooleanParameter(COLOR, isColor);
isDebug = myParser.getBooleanParameter(DEBUG, isDebug);
// System.out.println( "showParams:" + showParams );
// System.out.println( "showSource:" + showSource );
// System.out.println( "showSolution:" + showSolution );
// System.out.println( "showCookies:" + showCookies );
// System.out.println( "showRequest:" + showRequest );
if (content != null) {
response.setContentType("text/html");
PrintWriter out = new PrintWriter(response.getOutputStream());
out.print(content);
out.flush();
out.close();
}
}
public void updateLastAttackRequestInfo(HttpServletRequest request) {
// store cookies
Cookie[] cookies = request.getCookies();
if (cookies == null) {
this.cookiesOnLastRequest = new ArrayList<Cookie>();
} else {
this.cookiesOnLastRequest = Arrays.asList(cookies);
}
// store parameters
Map<String, String[]> parmMap = request.getParameterMap();
logger.info("PARM MAP: " + parmMap);
if (parmMap == null) {
this.parmsOnLastRequest = new ArrayList<RequestParameter>();
} else {
this.parmsOnLastRequest = new ArrayList<RequestParameter>();
for (String name : parmMap.keySet()) {
String[] values = parmMap.get(name);
String delim = "";
StringBuffer sb = new StringBuffer();
if (values != null && values.length > 0) {
for (String parm : values) {
sb.append(delim).append(parm);
delim = ",";
}
}
RequestParameter parm = new RequestParameter(name, sb.toString());
this.parmsOnLastRequest.add(parm);
}
}
}
private void restartLesson(int lessonId) {
AbstractLesson al = getLesson(lessonId);
System.out.println("Restarting lesson: " + al);
al.getLessonTracker(this).setCompleted(false);
if (al instanceof SequentialLessonAdapter) {
SequentialLessonAdapter sla = (SequentialLessonAdapter) al;
sla.getLessonTracker(this).setStage(1);
} else if (al instanceof RandomLessonAdapter) {
RandomLessonAdapter rla = (RandomLessonAdapter) al;
rla.setStage(this, rla.getStages()[0]);
}
}
/**
* @param string
*/
public void setHasHackableAdmin(String role) {
hasHackedHackableAdmin = (AbstractLesson.HACKED_ADMIN_ROLE.equals(role) & hasHackedHackableAdmin);
// if the user got the Admin=true parameter correct AND they accessed an admin screen
if (hasHackedHackableAdmin) {
completedHackableAdmin = true;
}
}
/**
* @return Returns the isDebug.
*/
public boolean isDebug() {
return isDebug;
}
/**
* @param header - request header value to return
* @return
*/
public String getHeader(String header) {
return getRequest().getHeader(header);
}
public String getNextHint() {
String hint = null;
// FIXME
int maxHints = getCurrentLesson().getHintCount(this);
if (hintNum < maxHints - 1) {
hintNum++;
// Hints are indexed from 0
getCurrentLesson().getLessonTracker(this).setMaxHintLevel(getHintNum() + 1);
hint = (String) getCurrentLesson().getHint(this, getHintNum());
}
return hint;
}
public String getPreviousHint() {
String hint = null;
if (hintNum > 0) {
hintNum--;
// Hints are indexed from 0
getCurrentLesson().getLessonTracker(this).setMaxHintLevel(getHintNum() + 1);
hint = (String) getCurrentLesson().getHint(this, getHintNum());
}
return hint;
}
public void setCurrentMenu(Integer ranking) {
currentMenu = ranking.intValue();
}
public int getCurrentMenu() {
return currentMenu;
}
public WebgoatContext getWebgoatContext() {
return webgoatContext;
}
public String getCurrrentLanguage() {
return currentLanguage;
}
/**
* @return the cookiesOnLastRequest
*/
public List<Cookie> getCookiesOnLastRequest() {
return cookiesOnLastRequest;
}
/**
* @return the parmsOnLastRequest
*/
public List<RequestParameter> getParmsOnLastRequest() {
return parmsOnLastRequest;
}
}