This tutorial looks at configuring a page to only be accessed via a secure channel (HTTPS).
The below example for this tutorial will implement a simple page to capture card details.
To configure the page to always be accessed via a secure channel, the following REST YAML path configuration is used:
secure: true
Setting secure: true in the path-level YAML file ensures any HTTP request to card is automatically redirected (307) to HTTPS before the handler runs.
To ease development, WoOF by default runs with a generic security key that is self signed. Typically for development and testing this will require trusting the key within the browser to access the page. This default setup should only be used for development/testing to avoid manual key setup.
For production, a trusted third-party signed security key is recommended to be configured.
Please also see the HttpServerLocation for details on configuring the web application's location for generation of the link URLs.
The page template content is as follows:
<!DOCTYPE html>
<html>
<body>
<h1>Enter card details</h1>
<form action="/card" method="POST">
Card number: <input type="text" name="number" th:value="${model.number}" size="19" /> <br />
Expiry date: <input type="text" name="month" th:value="${model.month}" size="2" /> /
<input type="text" name="year" th:value="${model.year}" size="4" />
CSC: <input type="text" name="csc" th:value="${model.csc}" size="3" /> <br />
<input type="submit" value="save" />
</form>
<a href="/main">Back to main page</a>
</body>
</html>
This is similar HTML to previous tutorials.
The logic for the page is the following:
public class CardLogic {
@Data
@HttpParameters
public static class CardDetails implements Serializable {
private static final long serialVersionUID = 1L;
private String number;
private String month;
private String year;
private String csc;
}
public CardDetails getTemplateData(CardDetails cardDetails, ServerHttpConnection connection) {
// Confirm a secure connection (not needed but included for tutorial)
if (!connection.isSecure()) {
throw new IllegalStateException();
}
// Return the card details for rendering
return cardDetails;
}
public void save(CardDetails cardDetails, ServerHttpConnection connection) {
// Confirm a secure connection (not needed but included for tutorial)
if (!connection.isSecure()) {
throw new IllegalStateException();
}
// Logic for processing the card details
}
}
Again this is similar to previous tutorials. The isSecure() check confirms that the connection is always HTTPS when the handler runs (due to the secure: true configuration).
The main page is included for completeness of the tutorial code.
<!DOCTYPE html>
<html>
<body>
<h1>Main Page</h1>
<a href="/card">Enter card details</a>
</body>
</html>
The unit test requests the page via HTTP and confirms the redirect to HTTPS returns the page successfully. The exception within the page logic ensures rendering the response only occurs over a secure channel (HTTPS).
@ExtendWith(OfficeFloorExtension.class)
public class SecurePageTest {
@RegisterExtension
public final HttpClientExtension client = new HttpClientExtension(true);
@Test
public void testSecurePage() throws Exception {
// Ensure redirect to secure access to page
this.assertHttpRequest("http://localhost:7878/card");
}
private void assertHttpRequest(String url) throws IOException {
HttpResponse response = this.client.execute(new HttpGet(url));
assertEquals(200, response.getStatusLine().getStatusCode(), "Should be successful (after possible redirect)");
String entity = EntityUtils.toString(response.getEntity());
assertTrue(entity.contains("<h1>Enter card details</h1>"),
"Should be rendering page as secure (and not exception)");
}
}
The next tutorial looks at securing a specific link.