Following up on my thread from yesterday, I've finished work on the SSL Interceptor, which can be added to the default stack and works as follows:
- If the associated action class is marked with the (custom) @SSLProtected annotation and it's an HTTP (non-SSL) GET request, then the interceptor will redirect to the https (SSL) version of the page. - Likewise, if it's an HTTPS (SSL) GET request and the action class does not have the annotation, then it will redirect to the http (non-SSL) version of the page. I've tested it with both browsers, with and without cookies, and it seems to work well, so I'll offer it to those interested. I'm not a regular contributor to the source code base, but if someone wants to submit this into the repository, feel free. /** * @name SSLProtected * @description Simple marker annotation indicating access to an action class should be protected * under SSL (Secure Sockets Layer) HTTP tunneling. * @version $Revision: $ * @author <a href="mailto:[EMAIL PROTECTED]">Shahak Nagiel</a> * $Id: $ */ @Retention(RetentionPolicy.RUNTIME) public @interface SSLProtected { } /** * @name SSLInterceptor * @description <p>This interceptor performs two functions: * <ul><li>If the associated action class is marked with the @SSLProtected annotation * and it's an HTTP (non-SSL) GET request, then the interceptor will redirect to the https (SSL) version of the page.</li> * <li>Likewise, if it's an HTTPS (SSL) GET request and the action class does not have the annotation, then it * will redirect to the http (non-SSL) version of the page.</li></ul> * @version $Revision: $ * @author <a href="mailto:[EMAIL PROTECTED]">Shahak Nagiel</a> * $Id: $ */ public class SSLInterceptor extends AbstractInterceptor { /** Creates a new instance of SSLInterceptor */ public SSLInterceptor() { super(); } /** * Defaults for HTTP and HTTPS ports. Can be overridden in web.xml with context parameters of the same name. */ final static int HTTP_PORT = 8080; final static int HTTPS_PORT = 8443; final static String HTTP_PORT_PARAM = "HTTP_PORT"; final static String HTTPS_PORT_PARAM = "HTTPS_PORT"; final static String HTTP_GET = "GET"; final static String SCHEME_HTTP = "http"; final static String SCHEME_HTTPS = "https"; /** * Redirect to SSL or non-SSL version of page as indicated by the presence (or absence) of the * @SSLProtected annotation on the action class. */ public String intercept(ActionInvocation invocation) throws Exception { // initialize request and response final ActionContext context = invocation.getInvocationContext (); final HttpServletRequest request = (HttpServletRequest) context.get(StrutsStatics.HTTP_REQUEST); final HttpServletResponse response = (HttpServletResponse) context.get(StrutsStatics.HTTP_RESPONSE); // check scheme String scheme = request.getScheme().toLowerCase(); // check method String method = request.getMethod().toUpperCase(); // If the action class uses the SSLProtected marker annotation, then see if we need to // redirect to the SSL protected version of this page if (invocation.getAction().getClass().isAnnotationPresent(SSLProtected.class)){ if (HTTP_GET.equals(method) && SCHEME_HTTP.equals(scheme)){ // initialize https port String httpsPortParam = request.getSession().getServletContext().getInitParameter(HTTP_PORT_PARAM); int httpsPort = httpsPortParam == null? HTTPS_PORT : Integer.parseInt(httpsPortParam); URI uri = new URI(SCHEME_HTTPS, null, request.getServerName(), httpsPort, response.encodeRedirectURL(request.getRequestURI()), request.getQueryString(), null); log.debug("Going to SSL mode, redirecting to " + uri.toString()); response.sendRedirect(uri.toString()); return null; } } // Otherwise, check to see if we need to redirect to the non-SSL version of this page else{ if (HTTP_GET.equals(method) && SCHEME_HTTPS.equals(scheme)){ // initialize http port String httpPortParam = request.getSession().getServletContext().getInitParameter(HTTPS_PORT_PARAM); int httpPort = httpPortParam == null? HTTP_PORT : Integer.parseInt(httpPortParam); URI uri = new URI(SCHEME_HTTP, null, request.getServerName(), httpPort, response.encodeRedirectURL(request.getRequestURI()), request.getQueryString(), null); log.debug("Going to non-SSL mode, redirecting to " + uri.toString()); response.sendRedirect(uri.toString()); return null; } } return invocation.invoke(); } // configure the logger for this class private static Log log = LogFactory.getLog(SSLInterceptor.class); }