Wicket HTTPS Tutorial Part Two: Creating Secure Forms

My previous blog entry described how you can create secure webpages by using the Apache Wicket framework. However, since a common use case of a web application is to provide a secure channel for processing information, my previous blog entry is not very useful without additional information. This blog entry will provide a part of the needed information by describing how you can create secure forms by using the techniques discussed in the first part of my Wicket HTTPS tutorial.

Required Steps

A secure form can be created by following these steps (The first and second step are described in my previous blog entry, so I will simply skip them here):

  1. Enabling and configuring the HTTPS support of Apache Wicket
  2. Creating a secured form
  3. Adding the secure form to a secure page

I decided to describe the third step by creating a simple login form, which stores the username to session after a successful login. The relevant parts of the example are described in following.

Enabling and Configuring the HTTPS Support of Apache Wicket

Enabling and configuring the HTTPS support of Apache Wicket can be divided in to two smaller phases:

  • Creating a custom session implementation
  • Creating a custom application class

I will describe these phases with more details next.

First, I created a session implementation, which can store the username of an authenticated user. I simply extended the org.apache.wicket.protocol.http.WebSession class, and added the methods needed to manipulate the username information. I also added a static get() method, which is used to obtain a reference to the session implementation. The source code of my session implementation is provided in following:

package net.kainulainen.wickethttps;

import org.apache.wicket.Request;
import org.apache.wicket.Session;
import org.apache.wicket.protocol.http.WebSession;

public class WicketHttpsSession extends WebSession {

    private String authenticatedUsername;

    public WicketHttpsSession(Request request) {
        super(request);
    }

    public static WicketHttpsSession get() {
        return (WicketHttpsSession) Session.get();
    }

    public String getAuthenticatedUsername() {
        return authenticatedUsername;
    }

    public void setAuthenticatedUsername(String authenticatedUsername) {
        this.authenticatedUsername = authenticatedUsername;
    }
}

Second, I created a custom application class, which overwrites the newSession(Request request, Response response) method of the org.apache.wicket.protocol.http.WebApplication class. This method returns a new instance of the WicketHttpsSession class, and ensures that Wicket uses my session implementation. The source code of my application class is available in following:

package net.kainulainen.wickethttps;

import org.apache.wicket.Request;
import org.apache.wicket.Response;
import org.apache.wicket.Session;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.https.HttpsConfig;
import org.apache.wicket.protocol.https.HttpsRequestCycleProcessor;
import org.apache.wicket.request.IRequestCycleProcessor;

public class WicketApplication extends WebApplication
{
    //Remember to enable and configure the HTTPS support of Apache Wicket as well!!    

    @Override
    public Session newSession(Request request, Response response) {
        return new WicketHttpsSession(request);
    }
}

Creating a Secure Form

Creating a secure form has got two smaller phases:

  • Creating a DTO for storing login information
  • Creating the actual form class which process the login information

These steps are explained with more details in this Section.

First, I created a simple DTO, which is used to store the login information entered by the user. The source code of the DTO is given in following:

package net.kainulainen.wickethttps.login;

import java.io.Serializable;

public class LoginDTO implements Serializable {
    private String username;
    private String password;

    public LoginDTO() {

    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Second, I created a simple form class, which processes the provided login information. The source code of the login form is provided in following:

package net.kainulainen.wickethttps.login;

import net.kainulainen.wickethttps.HomePage;
import net.kainulainen.wickethttps.WicketHttpsSession;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;

public class LoginForm extends StatelessForm<LoginDTO> {

    private static final String MESSAGE_KEY_LOGIN_FAILED = "error.login.failed";

    private static final String WICKET_ID_FEEDBACK = "feedback";
    private static final String WICKET_ID_USERNAME = "username";
    private static final String WICKET_ID_PASSWORD = "password";

    public LoginForm(String id) {
        super(id, new CompoundPropertyModel(new LoginDTO()));
        init();
    }

    public LoginForm(String id, IModel iModel) {
        super(id, iModel);
        init();
    }

    private void init() {
        add(new FeedbackPanel(WICKET_ID_FEEDBACK));
        add(new TextField(WICKET_ID_USERNAME)
                .setRequired(true)
        );
        add(new PasswordTextField(WICKET_ID_PASSWORD)
                .setRequired(true)
        );
    }

    @Override
    protected void onSubmit() {
        LoginDTO credentials = this.getModelObject();

        String username = credentials.getUsername();
        String password = credentials.getPassword();

        if (isValidUser(username, password)) {
            processSuccessfulLogin(username);
        } else {
            processFailedLogin();
        }
    }

    //A dummy way to test, if the username and password are correct. In real life, 
    //this method would naturally look quite different.
    private boolean isValidUser(String username, String password) {
        if (username.equals("foo") && (password.equals("bar"))) {
            return true;
        }
        return false;
    }

    private void processSuccessfulLogin(String username) {
        WicketHttpsSession currentSession = WicketHttpsSession.get();
        //Invalidates the current session and creates a new secure session.
        //The created secure session cannot be accessed when using http
        //protocol. This option should be used when only https protocol is
        //used after the user has logged in.
        //currentSession.replaceSession();
        currentSession.setAuthenticatedUsername(username);
        forwardUserToHomePage();
    }

    private void forwardUserToHomePage() {
        this.setResponsePage(HomePage.class);
    }

    private void processFailedLogin() {
        error(getString(MESSAGE_KEY_LOGIN_FAILED));
    }
}

Adding the Secure Form to a Secure Page

The last step is to add the created form class to a secure page. This ensures that the form submission is sent by using HTTPS protocol. The source code of the secure page is available in following:

package net.kainulainen.wickethttps.login;

import net.kainulainen.wickethttps.HomePage;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.protocol.https.RequireHttps;

@RequireHttps
public class SecureLoginPage extends WebPage {

    private static final String WICKET_ID_HOMEPAGE_LINK = "homepageLink";
    private static final String WICKET_ID_LOGINFORM = "loginForm";

    public SecureLoginPage(PageParameters parameters) {
        super(parameters);
        init();
    }

    protected void init() {
        add(new BookmarkablePageLink(WICKET_ID_HOMEPAGE_LINK, HomePage.class));
        add(new LoginForm(WICKET_ID_LOGINFORM));
    }
}

What is Next?

By following the instructions given in this blog entry, you can create a secure login form, which is submitted by using the HTTPS protocol. I have also create a simple example project (The project is tested with Apache Wicket 1.4.15), which will hopefully help you the understand the concepts described in this blog entry. You can run the example project by using the mvn jetty:run-war command (Remember to install Maven first).

The third part of the Wicket HTTPS tutorial describes a situation, where the form is added to a non secure page, but the form submission must be done by using the HTTPS protocol.

2 comments… add one
  • Ausainis Pekainis Sep 13, 2012 @ 14:13

    Code download is gone :(
    Could you please give a working link to the example code archive...

    • Petri Sep 13, 2012 @ 14:51

      Oops, my bad. The download should work now.

Leave a Reply