HELLO! Wicket

By Martijn Dashorst and Eelco Helenius

The following article is based on the book Wicket in Action, now available as part of Manning’s Early Access Program. The 375-page guide, written by two of the project’s earliest and most authoritative experts, shows you both the “how-to” and the “why” of Wicket.

Creating Secure Web Applications with Apache Wicket
In this article, we introduce how the popular web framework Wicket can help you create secure applications. Apache Wicket is an open source web framework available from the Apache Software Foundation. Wicket aims to simplify developing web applications in Java by providing a first-class component-oriented programming model, similar to JSF and .Net. Wicket components consist of just Java and HTML.

Wicket’s HTML templates are devoid of template logic: all markup manipulation is performed in Java code. This enforces a strong separation of concerns: HTML can be crafted by designers, and the backing logic by Java developers. If you’re new to Wicket, you can learn more about the framework by visiting the resources listed at the end of this article.

Securing your Wicket pages
There are multiple ways to protect your pages from unwanted access. A simple way to do so, for instance, is to let your pages extend a base page that checks authorization in its constructor. It could throw an exception or issue a redirect if authorization fails.

But using inheritance to take care of such things limits flexibility. It’s often better to implement authorization as a cross-cutting concern. Wicket has a mechanism that lets you do this: authorization strategies.

Introducing authorization strategies
The IAuthorizationStrategy interface is specially designed for securing web applications. As an example, you’ll create an implementation of this interface that denies unauthorized users access to a discounts page and that determines the visibility of an edit link depending on what kind of user is signed in.

The authorization strategy interface is defined in listing 1.

dashorst_listing1

This interface defines two separate events where authorization is checked:

  • On component creation
  • On specific actions on components after creation

Wicket implements checking on component creation using component-instantiation listeners. These listeners are registered with the application class, and they’re notified for every component that is constructed. Schematically, notification looks like the diagram in figure 1.

dashorst_figure1

Figure 1: instantiation listeners are notified when components are constructed.

Because the components are still in the first stage of constructing themselves, construction can be vetoed safely. Even if you execute authorization-dependent functionality in your constructor, if the listener vetoes, that functionality isn’t executed.

WARNING

Be very careful with component-instantiation listeners. They’re called for every component, so it’s important to keep the processing efficient. Also keep in mind that the components are still under construction. The only field that is set when the listeners are called is the parent field (and of course any static fields); the rest of the fields are yet to be initialized.

The code fragment in listing 2 is executed in the constructor of Wicket’s application base class.

listing2

Note in this code that authorizing component instantiation and taking action when authorization fails are encoded in two separate interfaces. This makes it easier to write one of them generically.

The default authorization-strategy setting allows all components to be constructed. The default implementation of the unauthorized instantiation listener throws an exception. You need custom behavior for both. In the next section, you’ll protect the page that displays discounts so that only logged-in users can access it.

Protecting the discounts page
Authorization strategies work on pages the same way they do on regular components. After all, pages are Wicket components like any others.
If you want to protect certain pages against unauthorized access, you first have to decide how you’ll differentiate between protected and unprotected pages. For instance, you can make it a rule that protected web pages must extend a certain base class, say ProtectedPage. (Note that the SigninPage should not extend ProtectedPage.) In figure 2, you can see this depicted in a diagram: DiscountsPage extends ProtectedPage, but SigninPage—which should be accessible without authenticating—extends directly from WebPage.

The schema in figure 2 shows the pages for this example.

figure2

Figure 2: Protected and unprotected pages

Next, you need to check whether the current page extends ProtectedPage; when it does, you have to check whether the requesting user is authenticated. If the user isn’t authenticated, and the requested page extends ProtectedPage, you must display the SigninPage. Otherwise, you’ll let the request go on.

To implement this behavior, you create a class that implements both the authorization check and the action to be taken when authorization fails:

listing3

The authorization check is implemented by providing the method isInstantiationAuthorized:

listing4

This approach is simple: you check whether the passed-in component extends ProtectedPage and, when it does, return whether the user is authenticated by querying the session object. If the check returns false, the other interface is called, for which you provide an implementation with the same class:

listing5

This is an interesting use of a special kind of exceptions in Wicket: abort exceptions. Such exceptions instruct Wicket to abort the current request and—depending on the implementation—take an alternative action. In this case, Wicket stops what it was doing and redirects to the sign-in page. Wicket will also remember how the current request was issued so it can reissue the request when the user successfully signs in. You did just that in the sign-in page. The class hierarchy in figure 3 shows some abort exceptions.

figure3

Figure 3: Examples of abort exceptions

Abort exceptions are designed to prematurely break off processing. Just as it’s considered bad practice to use exceptions for normal application flow (because doing so produces code that is harder to follow, and because using exceptions is relatively expensive), you shouldn’t go overboard using abort exceptions. This example is a good use of them, though, because if a user isn’t authorized, you want to stop constructing those objects right away. Not only is this approach more efficient, but it also does away with any risk of code being executed (such as performing database calls) that should never be done for an unauthorized user.

That’s the first step in protecting the discounts page. Users who aren’t authenticated are always redirected to the login page. Only successful authentication gives them access to the discounts page

To make this example complete, you need to protect the edit functionality from users who aren’t administrators. Although technically you could achieve this result using pages—you’d have a page that displays only discounts and another that also shows the edit link—it’s more elegant to use component-level authorization. The next section shows you how.

Disabling the edit link for unauthorized users
Let’s start with a straightforward implementation that hides the edit link from users who aren’t administrators. You do this by overriding isVisible and letting that method return true only when the user is authenticated and is an administrator. Listing 3 shows the code.

listing3a

Not much is wrong with this implementation. But if you were working on a large project with a lot of components and more complex authorization rules that differed between the components, you’d soon end up with a lot of code duplication.

A declarative approach works better here. Instead of overriding isVisble, you only declare the authorization attributes on the component. You also implement an algorithm that decides the authorization only once, and put it in a central place: the authorization strategy.

Authorization strategies work on pages the same way they do on regular components. After all, pages are Wicket components like any others.

listing4a

Because it doesn’t have any attributes, the annotation is really nothing more than a tagging interface. In real projects, you’d probably include more information, such as the kind of roles the annotation applies to. In this case, it functions like an on/off switch.

NOTE

In case you aren’t familiar with annotations,@Retention(RetentionPolicy.RUNTIME) means the annotation will be available at runtime, and @Target(ElementType.TYPE) declares that it will be used on class definitions.

You can’t define annotations on anonymous classes, so you have to make the link a private class. Listing 5 shows the link annotated with AdminOnly.

listing5a

The functionality you’re after is as follows: whenever you annotate a component with that annotation, it will be rendered only for users who are administrators. This is where you go back to the authorization strategy and implement the other method of the authorization-strategy interface: isActionAuthorized. Wicket calls this method to find out whether a component may be rendered and whether a component is enabled.

This information is used in a variety of ways, which may be specific for individual components. For instance, some form components set the disabled=”disabled” attribute on the tag they’re attached to, which makes the field read-only in the user’s browser. User input isn’t allowed on disabled components (this is an extra check, because disabled HTML input fields normally aren’t part of form submits); for example, links aren’t executed when they’re disabled (even if the user guesses them).

By default, Wicket ships with checks on enabled and render, but these cases can be extended if users wish. For this example, you only care about the render action, which is defined in Component as follows:

listing9

Listing 6 shows the implementation of the action check.

listing6a

As you can see, the implementation first checks whether the action is a render action. Then, the implementation checks whether the component is annotated with an AdminOnly; if it is, the implementation checks whether the user is an administrator.
When you place the user panel on the discount page, it looks like figure 4.

figure4

Figure 4: Signed in as a normal user

Figure 4 shows what the page looks like when you’re logged in as a regular user. There is no trace of the edit link. But in figure 5, the same page is rendered for a user who is an administrator.

figure5

Figure 5: Signed in as an administrator

Violà: the edit link is available, and the discounts page is safe!

Summary
In this article, we explained how to implement a simple custom-authorization strategy to protect a discounts page. We looked at how to configure the strategy to redirect to an intermediate login page if the user isn’t yet authenticated. Then, you implemented some component-level authorization, protecting the edit link from users without sufficient rights.

Wicket’s security capabilities are broader than discussed in this article. For instance, we haven’t looked at the various ways to implement authentication, or how to apply authorization to URLs. Wicket ships with an example security framework called wicket-auth-roles, which is discussed in Wicket in Action, a forthcoming Manning title. This framework provides annotations and a couple of roles to secure your pages. By design, it’s basic and a great starting point for your own custom-authorization implementation.

To learn more about Apache Wicket, please visit the following resources:

  • http://wicket.apache.org—The Apache Wicket web site.
  • http://manning.com/dashorst—Wicket in Action: the authoritative, comprehensive guide for Java developers building Wicket-based web applications. This book is written by two of the project’s most authoritative experts.
  • http://manning.com/dashorst/meap_wicketch1.pdf—“What is Wicket?” A gentle introduction to the Wicket framework (free chapter 1 from Wicket in Action).