001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018: /*
019: * SchemeEnforcementFilter.java
020: *
021: * Created on September 16, 2005, 3:17 PM
022: */
023:
024: package org.apache.roller.ui.core.filters;
025:
026: import java.io.IOException;
027: import java.util.HashSet;
028: import java.util.Iterator;
029: import java.util.Set;
030: import javax.servlet.Filter;
031: import javax.servlet.FilterChain;
032: import javax.servlet.FilterConfig;
033: import javax.servlet.ServletException;
034: import javax.servlet.ServletRequest;
035: import javax.servlet.ServletResponse;
036: import javax.servlet.http.HttpServletRequest;
037: import javax.servlet.http.HttpServletResponse;
038: import org.apache.commons.logging.Log;
039: import org.apache.commons.logging.LogFactory;
040: import org.apache.roller.config.RollerConfig;
041:
042: /**
043: * The SchemeEnforcementFilter is provided for Roller sites that enable secure
044: * logins and want to ensure that only login urls are used under https.
045: *
046: * @author Allen Gilliland
047: *
048: * @web.filter name="SchemeEnforcementFilter"
049: */
050: public class SchemeEnforcementFilter implements Filter {
051:
052: private static Log mLogger = LogFactory
053: .getLog(SchemeEnforcementFilter.class);
054:
055: private FilterConfig filterConfig = null;
056:
057: private boolean schemeEnforcementEnabled = false;
058: private boolean secureLoginEnabled = false;
059: private int httpPort = 80;
060: private int httpsPort = 443;
061: private String httpsHeaderName = null;
062: private String httpsHeaderValue = null;
063:
064: private Set allowedUrls = new HashSet();
065:
066: /**
067: * Process filter.
068: *
069: * We'll take the incoming request and first determine if this is a
070: * secure request. If the request is secure then we'll see if it matches
071: * one of the allowed secure urls, if not then we will redirect back out
072: * of https.
073: */
074: public void doFilter(ServletRequest request,
075: ServletResponse response, FilterChain chain)
076: throws IOException, ServletException {
077:
078: if (this .schemeEnforcementEnabled && this .secureLoginEnabled) {
079:
080: HttpServletRequest req = (HttpServletRequest) request;
081: HttpServletResponse res = (HttpServletResponse) response;
082:
083: mLogger.debug("checking path = " + req.getServletPath());
084:
085: if (!request.isSecure()
086: && allowedUrls.contains(req.getServletPath())) {
087: // http insecure request that should be over https
088: String redirect = "https://" + req.getServerName();
089:
090: if (this .httpsPort != 443)
091: redirect += ":" + this .httpsPort;
092:
093: redirect += req.getRequestURI();
094:
095: if (req.getQueryString() != null)
096: redirect += "?" + req.getQueryString();
097:
098: mLogger.debug("Redirecting to " + redirect);
099: res.sendRedirect(redirect);
100: return;
101:
102: } else if (request.isSecure()
103: && !allowedUrls.contains(req.getServletPath())) {
104: // https secure request that should be over http
105: String redirect = "http://" + req.getServerName();
106:
107: if (this .httpPort != 80)
108: redirect += ":" + this .httpPort;
109:
110: redirect += req.getRequestURI();
111:
112: if (req.getQueryString() != null)
113: redirect += "?" + req.getQueryString();
114:
115: mLogger.debug("Redirecting to " + redirect);
116: res.sendRedirect(redirect);
117: return;
118: }
119: }
120:
121: chain.doFilter(request, response);
122: }
123:
124: public void destroy() {
125: }
126:
127: /**
128: * Filter init.
129: *
130: * We are just collecting init properties which we'll use for each request.
131: */
132: public void init(FilterConfig filterConfig) {
133: this .filterConfig = filterConfig;
134:
135: // determine if we are doing scheme enforcement
136: this .schemeEnforcementEnabled = RollerConfig
137: .getBooleanProperty("schemeenforcement.enabled");
138: this .secureLoginEnabled = RollerConfig
139: .getBooleanProperty("securelogin.enabled");
140:
141: if (this .schemeEnforcementEnabled && this .secureLoginEnabled) {
142: // gather some more properties
143: String http_port = RollerConfig
144: .getProperty("securelogin.http.port");
145: String https_port = RollerConfig
146: .getProperty("securelogin.https.port");
147:
148: try {
149: this .httpPort = Integer.parseInt(http_port);
150: this .httpsPort = Integer.parseInt(https_port);
151: } catch (NumberFormatException nfe) {
152: // ignored ... guess we'll have to use the defaults
153: mLogger.warn("error with secure login ports", nfe);
154: }
155:
156: // finally, construct our list of allowable https urls
157: String urls = RollerConfig
158: .getProperty("schemeenforcement.https.urls");
159: String[] urlsArray = urls.split(",");
160: for (int i = 0; i < urlsArray.length; i++)
161: this .allowedUrls.add(urlsArray[i]);
162:
163: // some logging for the curious
164: mLogger.info("Scheme enforcement = enabled");
165: if (mLogger.isDebugEnabled()) {
166: mLogger.debug("allowed urls are:");
167: for (Iterator it = this.allowedUrls.iterator(); it
168: .hasNext();)
169: mLogger.debug(it.next());
170: }
171: }
172: }
173:
174: }
|