Author: ivaynberg
Date: Fri Apr 17 17:37:36 2009
New Revision: 766095

URL: http://svn.apache.org/viewvc?rev=766095&view=rev
Log:
https/http switching support, WICKET-2229
Issue: WICKET-2229

Added:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
   (with props)
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsRequestCycleProcessor.java
   (with props)
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/RequireHttps.java
   (with props)
    
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestTarget.java
   (with props)

Added: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java?rev=766095&view=auto
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
 (added)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
 Fri Apr 17 17:37:36 2009
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.protocol.https;
+
+/**
+ * Configuration for http-https switching
+ * 
+ * @see HttpsRequestCycleProcessor
+ */
+public class HttpsConfig
+{
+       private int httpPort = 80;
+       private int httpsPort = 443;
+
+       /**
+        * Constructor
+        */
+       public HttpsConfig()
+       {
+
+       }
+
+       /**
+        * Constructor
+        * 
+        * @param httpPort
+        *            http port
+        * @param httpsPort
+        *            https port
+        */
+       public HttpsConfig(int httpPort, int httpsPort)
+       {
+               this.httpPort = httpPort;
+               this.httpsPort = httpsPort;
+       }
+
+
+       /**
+        * Sets http port
+        * 
+        * @param httpPort
+        */
+       public void setHttpPort(int httpPort)
+       {
+               this.httpPort = httpPort;
+       }
+
+       /**
+        * Sets https port
+        * 
+        * @param httpsPort
+        */
+       public void setHttpsPort(int httpsPort)
+       {
+               this.httpsPort = httpsPort;
+       }
+
+       /**
+        * @return http port
+        */
+       public int getHttpPort()
+       {
+               return httpPort;
+       }
+
+       /**
+        * @return https port
+        */
+       public int getHttpsPort()
+       {
+               return httpsPort;
+       }
+}

Propchange: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsRequestCycleProcessor.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsRequestCycleProcessor.java?rev=766095&view=auto
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsRequestCycleProcessor.java
 (added)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsRequestCycleProcessor.java
 Fri Apr 17 17:37:36 2009
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.protocol.https;
+
+import org.apache.wicket.IRequestTarget;
+import org.apache.wicket.RequestCycle;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebRequestCycleProcessor;
+import org.apache.wicket.protocol.https.SwitchProtocolRequestTarget.Protocol;
+import org.apache.wicket.request.RequestParameters;
+import 
org.apache.wicket.request.target.component.IBookmarkablePageRequestTarget;
+import org.apache.wicket.request.target.component.IPageRequestTarget;
+
+
+/**
+ * Request cycle processor that can switch between http and https protocols 
based on the
+ * {...@link RequireHttps} annotation.
+ * 
+ * Once this processor is installed, any page annotated with the {...@link 
RequireHttps} annotation
+ * will be served over https, while any page lacking the annotation will be 
served over http. The
+ * annotation can be placed on a super class or an interface that a page 
implements.
+ * 
+ * To install this processor:
+ * 
+ * <pre>
+ * class MyApplication extends WebApplication
+ * {
+ *     &#064;Override
+ *     protected IRequestCycleProcessor newRequestCycleProcessor()
+ *     {
+ *             return new SecureRequestCycleProcessor(config);
+ *     }
+ * }
+ * </pre>
+ * 
+ * <b>Notes</b>: According to servlet spec a cookie created on an https 
request is marked as secure,
+ * such cookies are not available for http requests. What this means is that a 
session started over
+ * https will not be propagated to further http calls because JSESSIONID 
cookie will be marked as
+ * secure and not available to http requests. This entails that unless a 
session is created and
+ * bound on http prior to using an https request any wicket pages or session 
values stored in the
+ * https session will not be available to further http requests. If your 
application requires a
+ * http-&gt;https-&gt;http interactions (such as the case where only a login 
page and my account
+ * pages are secure) you must make sure a session is created and stored in the 
http request prior to
+ * the first http-&gt;https redirect.
+ */
+public class HttpsRequestCycleProcessor extends WebRequestCycleProcessor
+{
+       private final HttpsConfig portConfig;
+
+       /**
+        * Constructor
+        * 
+        * @param httpsConfig
+        *            configuration
+        */
+       public HttpsRequestCycleProcessor(HttpsConfig httpsConfig)
+       {
+               portConfig = httpsConfig;
+       }
+
+       /**
+        * @return configuration
+        */
+       public HttpsConfig getConfig()
+       {
+               return portConfig;
+       }
+
+       /**
+        * Checks if the class has a {...@link RequireHttps} annotation
+        * 
+        * @param klass
+        * @return true if klass has the annotation
+        */
+       private boolean hasSecureAnnotation(Class<?> klass)
+       {
+               for (Class<?> c : klass.getInterfaces())
+               {
+                       if (hasSecureAnnotation(c))
+                       {
+                               return true;
+                       }
+               }
+               if (klass.getAnnotation(RequireHttps.class) != null)
+               {
+                       return true;
+               }
+               if (klass.getSuperclass() != null)
+               {
+                       return hasSecureAnnotation(klass.getSuperclass());
+               }
+               else
+               {
+                       return false;
+               }
+       }
+
+       /**
+        * Gets page class from a request target
+        * 
+        * @param target
+        * @return page class if there is one, null otherwise
+        */
+       private Class<?> getPageClass(IRequestTarget target)
+       {
+               if (target instanceof IPageRequestTarget)
+               {
+                       return 
((IPageRequestTarget)target).getPage().getClass();
+               }
+               else if (target instanceof IBookmarkablePageRequestTarget)
+               {
+                       return 
((IBookmarkablePageRequestTarget)target).getPageClass();
+               }
+               else
+               {
+                       return null;
+               }
+       }
+
+       /** {...@inheritdoc} */
+       @Override
+       public IRequestTarget resolve(RequestCycle rc, RequestParameters rp)
+       {
+               // we need to persist the session before a redirect to https so 
the session lasts across
+               // both http and https calls.
+               Session.get().bind();
+
+               IRequestTarget target = super.resolve(rc, rp);
+               Class<?> pageClass = getPageClass(target);
+               if (pageClass != null)
+               {
+                       IRequestTarget redirect = null;
+                       if (hasSecureAnnotation(pageClass))
+                       {
+                               redirect = 
SwitchProtocolRequestTarget.requireProtocol(Protocol.HTTPS);
+                       }
+                       else
+                       {
+                               redirect = 
SwitchProtocolRequestTarget.requireProtocol(Protocol.HTTP);
+                       }
+                       if (redirect != null)
+                       {
+                               return redirect;
+                       }
+
+               }
+               return target;
+       }
+}

Propchange: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/HttpsRequestCycleProcessor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/RequireHttps.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/RequireHttps.java?rev=766095&view=auto
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/RequireHttps.java
 (added)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/RequireHttps.java
 Fri Apr 17 17:37:36 2009
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.protocol.https;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a page as requiring https.
+ * 
+ * @see HttpsRequestCycleProcessor
+ * 
+ */
+...@retention(RetentionPolicy.RUNTIME)
+...@target(ElementType.TYPE)
+public @interface RequireHttps {
+
+}

Propchange: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/RequireHttps.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestTarget.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestTarget.java?rev=766095&view=auto
==============================================================================
--- 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestTarget.java
 (added)
+++ 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestTarget.java
 Fri Apr 17 17:37:36 2009
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.protocol.https;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.wicket.IRequestTarget;
+import org.apache.wicket.RequestCycle;
+import org.apache.wicket.protocol.http.WebRequest;
+import org.apache.wicket.protocol.http.WebResponse;
+
+/**
+ * Request target that performs redirects across http and https
+ */
+class SwitchProtocolRequestTarget implements IRequestTarget
+{
+       /**
+        * Protocols
+        */
+       public enum Protocol {
+               /*** HTTP */
+               HTTP,
+               /** HTTPS */
+               HTTPS,
+               /** CURRENT */
+               PRESERVE_CURRENT
+       }
+
+       private final Protocol protocol;
+
+       /**
+        * Constructor
+        * 
+        * @param protocol
+        *            required protocol
+        */
+       public SwitchProtocolRequestTarget(Protocol protocol)
+       {
+               if (protocol == null)
+               {
+                       throw new IllegalArgumentException("Argument 'protocol' 
may not be null.");
+               }
+               if (protocol == Protocol.PRESERVE_CURRENT)
+               {
+                       throw new IllegalArgumentException("Argument 'protocol' 
may not have value '" +
+                               Protocol.PRESERVE_CURRENT.toString() + "'.");
+               }
+               this.protocol = protocol;
+       }
+
+       /** {...@inheritdoc} */
+       public void detach(RequestCycle requestCycle)
+       {
+
+       }
+
+       /**
+        * Rewrite the url using the specified protocol
+        * 
+        * @param protocol
+        * @param port
+        * @param request
+        * @return url
+        */
+       private String getUrl(String protocol, Integer port, HttpServletRequest 
request)
+       {
+               StringBuilder result = new StringBuilder();
+               result.append(protocol);
+               result.append("://");
+               result.append(request.getServerName());
+               if (port != null)
+               {
+                       result.append(":");
+                       result.append(port);
+               }
+               result.append(request.getRequestURI());
+               if (request.getQueryString() != null)
+               {
+                       result.append("?");
+                       result.append(request.getQueryString());
+               }
+               return result.toString();
+       }
+
+       /**
+        * {...@inheritdoc}
+        */
+       public void respond(RequestCycle requestCycle)
+       {
+               WebRequest webRequest = (WebRequest)requestCycle.getRequest();
+               HttpServletRequest request = webRequest.getHttpServletRequest();
+
+               HttpsRequestCycleProcessor processor = 
(HttpsRequestCycleProcessor)requestCycle.getProcessor();
+               Integer port = null;
+               if (protocol == Protocol.HTTP)
+               {
+                       if (processor.getConfig().getHttpPort() != 80)
+                       {
+                               port = processor.getConfig().getHttpPort();
+                       }
+               }
+               else if (protocol == Protocol.HTTPS)
+               {
+                       if (processor.getConfig().getHttpsPort() != 443)
+                       {
+                               port = processor.getConfig().getHttpsPort();
+                       }
+               }
+
+               String url = getUrl(protocol.toString().toLowerCase(), port, 
request);
+
+               WebResponse response = (WebResponse)requestCycle.getResponse();
+
+               // an attempt to rewrite a secure jsessionid into nonsecure, 
doesnt seem to work
+               // Session session = Session.get();
+               // if (!session.isTemporary())
+               // {
+               // response.addCookie(new Cookie("JSESSIONID", 
session.getId()));
+               // }
+
+               response.redirect(url);
+       }
+
+       /**
+        * Returns a target that can be used to redirect to the specified 
protocol. If no change is
+        * required null will be returned.
+        * 
+        * @param protocol
+        *            required protocol
+        * @return request target or null
+        */
+       public static IRequestTarget requireProtocol(Protocol protocol)
+       {
+               RequestCycle requestCycle = RequestCycle.get();
+               WebRequest webRequest = (WebRequest)requestCycle.getRequest();
+               HttpServletRequest request = webRequest.getHttpServletRequest();
+               if (protocol == null || protocol == Protocol.PRESERVE_CURRENT ||
+                       
request.getScheme().equals(protocol.toString().toLowerCase()))
+               {
+                       return null;
+               }
+               else
+               {
+                       return new SwitchProtocolRequestTarget(protocol);
+               }
+       }
+
+}

Propchange: 
wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestTarget.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to