blob: bbe9ef7e3d183c6a33f004cc5b1795d35e1eb569 [file] [log] [blame]
----
Securing the application with HTTPS
----
Securing your application with HTTPS
Tapestry assumes your application will be primarily deployed as a standard web application, using HTTP
(not HTTPS) as the transport mechanism.
However, many applications will need to have some of their pages secured: only accessible via HTTPS.
This could be a login page, or a product ordering wizard, or administrative pages.
All that is necessary to mark a page as secure is to add
the {{{../../apidocs/org/apache/tapestry5/annotations/Secure.html}Secure}} annotation to the page class:
----
@Secure
public class ProcessOrder
{
. . .
}
----
When a page is marked as secure, Tapestry will ensure that access to that page uses HTTPS.
All links to the page will use the "https" protocol.
If an attempt is made to access a secure page using a non-secure request (a normal HTTP request),
Tapestry will send an HTTPS redirect to the client.
Links to non-secure pages from a secure page will do the reverse: a complete URL with an "http"
protocol will be used. In other words, Tapestry manages the transition from insecure to secure and back again.
Links to other (secure) pages <and to assets> will be based on relative URLs and, therefore, secure.
The rationale behind using secure links to assets from secure pages is that it prevents
the client web browser from reporting a mixed security level.
Securing Multiple Pages
Rather than placing an @Secure annotation on individual pages, it is possible to
enable security for folders of pages. All pages in or beneath the folder will be secured.
This is accomplished by making a contribution to the
{{{../../apidocs/org/apache/tapestry5/services/MetaDataLocator.html}MetaDataLocator}}
service configuration. For example, to secure all pages in the "admin" folder:
----
public void contributeMetaDataLocator(MappedConfiguration<String,String> configuration)
{
configuration.put("admin:" + TapestryConstants.SECURE_PAGE, "true");
}
----
Here "admin" is the folder name, and the colon is a separator between the folder name
and the the meta data key.
SECURE_PAGE is a public constant for value "tapestry.secure-page";
When Tapestry is determining if a page is secure or not, it starts by checking for
the @Secure annotation, then it consults the MetaDataLocator service.
If you want to make your entire application secure:
---
public void contributeMetaDataLocator(MappedConfiguration<String,String> configuration)
{
configuration.put(TapestryConstants.SECURE_PAGE, "true");
}
----
With no colon, the meta data applies to the entire application (including any component libraries
used in the application).
Base URL Support
When Tapestry switches back and forth between secure and unsecure mode, it must
create a full URL (rather than a relative URL) that identifies the protocol, server host name
and perhaps even a port number.
That can be a stumbling point, especially the server host name. In a cluster, behind a fire wall,
the server host name available to Tapestry, via the <<<HttpServletRequest.getServerName()>>> method,
is often <not> the server name the client web browser sees ... instead it is the
name of the internal server behind the firewall. The firewall server has the correct name
from the web browser's point of view.
Because of this, Tapestry includes a hook to allow you to override how these default
URLs are created: the
{{{../../apidocs/org/apache/tapestry5/services/BaseURLSource.html}BaseURLSource}} service.
The default implementation is based on just the getServerName() method; it's often not the
correct choice even for development.
Fortunately, it is very easy to override this implementation. Here's an example of an override
that uses the default port numbers that
the {{{http://jetty.mortbay.com}Jetty servlet container}} uses for normal HTTP (port 8080) and for
secure HTTPS (port 8443):
----
public void contributeAlias(Configuration<AliasContribution> configuration)
{
BaseURLSource source = new BaseURLSource()
{
public String getBaseURL(boolean secure)
{
String protocol = secure ? "https" : "http";
int port = secure ? 8080 : 8443;
return String.format("%s://localhost:%d", protocol, port);
}
};
configuration.add(AliasContribution.create(BaseURLSource.class, source));
}
----
This override is hardcoded to generate URLs for localhost; as such you might use it for development
but certainly not in production.
The Alias service exists just for these kinds of overrides; it allows a late-binding
to a customized implementation of the BaseURLSource service that hides the built-in
Tapestry implementation.
Application Server Configuration
Setting up HTTPS support varies from application server to application server.
* Jetty:
* {{{http://docs.codehaus.org/display/JETTY/How+to+configure+SSL}Jetty 6}}
* Tomcat:
* {{{http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html}Version 6.0}}
* {{{http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html}Version 5.5}}