You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@roller.apache.org by Greg Huber <gr...@gmail.com> on 2012/01/01 18:09:45 UTC

SchemeEnforcementFilter mods

Dave,

To get the SchemeEnforcementFilter to work correctly over SSL without
the pesky mixed content warning we need something like the below:

roller.properties

schemeenforcement.https.ignored=css,gif,png,js

//

public class SchemeEnforcementFilter implements Filter {

	private static Log mLogger = LogFactory
			.getLog(SchemeEnforcementFilter.class);

	private FilterConfig filterConfig = null;

	private boolean schemeEnforcementEnabled = false;
	private boolean secureLoginEnabled = false;
	private int httpPort = 80;
	private int httpsPort = 443;
	private String httpsHeaderName = null;
	private String httpsHeaderValue = null;

	private Set allowedUrls = new HashSet();
	private Set<String> ignored = new HashSet<String>();

	/**
	 * Process filter.
	 *
	 * We'll take the incoming request and first determine if this is a secure
	 * request. If the request is secure then we'll see if it matches one of the
	 * allowed secure urls, if not then we will redirect back out of https.
	 */
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {

			HttpServletRequest req = (HttpServletRequest) request;
			HttpServletResponse res = (HttpServletResponse) response;

			mLogger.debug("checking path = " + req.getServletPath());

			if (!request.isSecure()
					&& allowedUrls.contains(req.getServletPath())) {
				// http insecure request that should be over https
				String redirect = "https://" + req.getServerName();

				if (this.httpsPort != 443)
					redirect += ":" + this.httpsPort;

				redirect += req.getRequestURI();

				if (req.getQueryString() != null)
					redirect += "?" + req.getQueryString();

				mLogger.debug("Redirecting to " + redirect);
				res.sendRedirect(redirect);
				return;

			} else if (request.isSecure()
					&& !isIgnoredURL(req.getServletPath())
					&& !allowedUrls.contains(req.getServletPath())) {
				// https secure request that should be over http
				String redirect = "http://" + req.getServerName();

				if (this.httpPort != 80)
					redirect += ":" + this.httpPort;

				redirect += req.getRequestURI();

				if (req.getQueryString() != null)
					redirect += "?" + req.getQueryString();

				mLogger.debug("Redirecting to " + redirect);
				res.sendRedirect(redirect);
				return;
			}
		}

		chain.doFilter(request, response);
	}

	/**
	 * Checks if the url is to be ignored.
	 *
	 * @param theUrl
	 *            the the url
	 *
	 * @return true, if the url is to be ignored.
	 */
	private boolean isIgnoredURL(String theUrl) {

		int i = theUrl.lastIndexOf(".");

		if (i <= 0 || i == theUrl.length() - 1)
			return false;

		return ignored.contains(theUrl.substring(i + 1));

	}

	public void destroy() {
	}

	/**
	 * Filter init.
	 *
	 * We are just collecting init properties which we'll use for each request.
	 */
	public void init(FilterConfig filterConfig) {
		this.filterConfig = filterConfig;

		// determine if we are doing scheme enforcement
		this.schemeEnforcementEnabled = WebloggerConfig
				.getBooleanProperty("schemeenforcement.enabled");
		this.secureLoginEnabled = WebloggerConfig
				.getBooleanProperty("securelogin.enabled");

		if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
			// gather some more properties
			String http_port = WebloggerConfig
					.getProperty("securelogin.http.port");
			String https_port = WebloggerConfig
					.getProperty("securelogin.https.port");

			try {
				this.httpPort = Integer.parseInt(http_port);
				this.httpsPort = Integer.parseInt(https_port);
			} catch (NumberFormatException nfe) {
				// ignored ... guess we'll have to use the defaults
				mLogger.warn("error with secure login ports", nfe);
			}

			// finally, construct our list of allowable https urls
			String urls = WebloggerConfig
					.getProperty("schemeenforcement.https.urls");
			String[] urlsArray = urls.split(",");
			for (int i = 0; i < urlsArray.length; i++)
				this.allowedUrls.add(urlsArray[i]);

			// construct our list of ignored https extensions
			urls = WebloggerConfig
					.getProperty("schemeenforcement.https.ignored");
			urlsArray = urls.split(",");
			for (int i = 0; i < urlsArray.length; i++)
				this.ignored.add(urlsArray[i]);

			// some logging for the curious
			mLogger.info("Scheme enforcement = enabled");
			if (mLogger.isDebugEnabled()) {
				mLogger.debug("allowed urls are:");
				for (Iterator it = this.allowedUrls.iterator(); it.hasNext();)
					mLogger.debug(it.next());
				mLogger.debug("ignored extensions are:");
				for (Iterator it = this.ignored.iterator(); it.hasNext();)
					mLogger.debug(it.next());
			}
		}
	}

}

Cheers Greg

Re: SchemeEnforcementFilter mods

Posted by David Johnson <sn...@gmail.com>.
That looks good, especially if you have tested it.
Please commit to trunk if you've got some time.

- Dave



On Jan 1, 2012, at 12:09 PM, Greg Huber wrote:

> Dave,
> 
> To get the SchemeEnforcementFilter to work correctly over SSL without
> the pesky mixed content warning we need something like the below:
> 
> roller.properties
> 
> schemeenforcement.https.ignored=css,gif,png,js
> 
> //
> 
> public class SchemeEnforcementFilter implements Filter {
> 
> 	private static Log mLogger = LogFactory
> 			.getLog(SchemeEnforcementFilter.class);
> 
> 	private FilterConfig filterConfig = null;
> 
> 	private boolean schemeEnforcementEnabled = false;
> 	private boolean secureLoginEnabled = false;
> 	private int httpPort = 80;
> 	private int httpsPort = 443;
> 	private String httpsHeaderName = null;
> 	private String httpsHeaderValue = null;
> 
> 	private Set allowedUrls = new HashSet();
> 	private Set<String> ignored = new HashSet<String>();
> 
> 	/**
> 	 * Process filter.
> 	 *
> 	 * We'll take the incoming request and first determine if this is a secure
> 	 * request. If the request is secure then we'll see if it matches one of the
> 	 * allowed secure urls, if not then we will redirect back out of https.
> 	 */
> 	public void doFilter(ServletRequest request, ServletResponse response,
> 			FilterChain chain) throws IOException, ServletException {
> 
> 		if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
> 
> 			HttpServletRequest req = (HttpServletRequest) request;
> 			HttpServletResponse res = (HttpServletResponse) response;
> 
> 			mLogger.debug("checking path = " + req.getServletPath());
> 
> 			if (!request.isSecure()
> 					&& allowedUrls.contains(req.getServletPath())) {
> 				// http insecure request that should be over https
> 				String redirect = "https://" + req.getServerName();
> 
> 				if (this.httpsPort != 443)
> 					redirect += ":" + this.httpsPort;
> 
> 				redirect += req.getRequestURI();
> 
> 				if (req.getQueryString() != null)
> 					redirect += "?" + req.getQueryString();
> 
> 				mLogger.debug("Redirecting to " + redirect);
> 				res.sendRedirect(redirect);
> 				return;
> 
> 			} else if (request.isSecure()
> 					&& !isIgnoredURL(req.getServletPath())
> 					&& !allowedUrls.contains(req.getServletPath())) {
> 				// https secure request that should be over http
> 				String redirect = "http://" + req.getServerName();
> 
> 				if (this.httpPort != 80)
> 					redirect += ":" + this.httpPort;
> 
> 				redirect += req.getRequestURI();
> 
> 				if (req.getQueryString() != null)
> 					redirect += "?" + req.getQueryString();
> 
> 				mLogger.debug("Redirecting to " + redirect);
> 				res.sendRedirect(redirect);
> 				return;
> 			}
> 		}
> 
> 		chain.doFilter(request, response);
> 	}
> 
> 	/**
> 	 * Checks if the url is to be ignored.
> 	 *
> 	 * @param theUrl
> 	 *            the the url
> 	 *
> 	 * @return true, if the url is to be ignored.
> 	 */
> 	private boolean isIgnoredURL(String theUrl) {
> 
> 		int i = theUrl.lastIndexOf(".");
> 
> 		if (i <= 0 || i == theUrl.length() - 1)
> 			return false;
> 
> 		return ignored.contains(theUrl.substring(i + 1));
> 
> 	}
> 
> 	public void destroy() {
> 	}
> 
> 	/**
> 	 * Filter init.
> 	 *
> 	 * We are just collecting init properties which we'll use for each request.
> 	 */
> 	public void init(FilterConfig filterConfig) {
> 		this.filterConfig = filterConfig;
> 
> 		// determine if we are doing scheme enforcement
> 		this.schemeEnforcementEnabled = WebloggerConfig
> 				.getBooleanProperty("schemeenforcement.enabled");
> 		this.secureLoginEnabled = WebloggerConfig
> 				.getBooleanProperty("securelogin.enabled");
> 
> 		if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
> 			// gather some more properties
> 			String http_port = WebloggerConfig
> 					.getProperty("securelogin.http.port");
> 			String https_port = WebloggerConfig
> 					.getProperty("securelogin.https.port");
> 
> 			try {
> 				this.httpPort = Integer.parseInt(http_port);
> 				this.httpsPort = Integer.parseInt(https_port);
> 			} catch (NumberFormatException nfe) {
> 				// ignored ... guess we'll have to use the defaults
> 				mLogger.warn("error with secure login ports", nfe);
> 			}
> 
> 			// finally, construct our list of allowable https urls
> 			String urls = WebloggerConfig
> 					.getProperty("schemeenforcement.https.urls");
> 			String[] urlsArray = urls.split(",");
> 			for (int i = 0; i < urlsArray.length; i++)
> 				this.allowedUrls.add(urlsArray[i]);
> 
> 			// construct our list of ignored https extensions
> 			urls = WebloggerConfig
> 					.getProperty("schemeenforcement.https.ignored");
> 			urlsArray = urls.split(",");
> 			for (int i = 0; i < urlsArray.length; i++)
> 				this.ignored.add(urlsArray[i]);
> 
> 			// some logging for the curious
> 			mLogger.info("Scheme enforcement = enabled");
> 			if (mLogger.isDebugEnabled()) {
> 				mLogger.debug("allowed urls are:");
> 				for (Iterator it = this.allowedUrls.iterator(); it.hasNext();)
> 					mLogger.debug(it.next());
> 				mLogger.debug("ignored extensions are:");
> 				for (Iterator it = this.ignored.iterator(); it.hasNext();)
> 					mLogger.debug(it.next());
> 			}
> 		}
> 	}
> 
> }
> 
> Cheers Greg