Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Alpine/alpine/src/main/java/alpine/filters/WhitelistUrlFilter.java /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
163 lines (148 sloc)
6.22 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * This file is part of Alpine. | |
| * | |
| * Licensed 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. | |
| * | |
| * SPDX-License-Identifier: Apache-2.0 | |
| * Copyright (c) Steve Springett. All Rights Reserved. | |
| */ | |
| package alpine.filters; | |
| import org.apache.commons.lang3.StringUtils; | |
| import javax.servlet.Filter; | |
| import javax.servlet.FilterChain; | |
| import javax.servlet.FilterConfig; | |
| import javax.servlet.ServletException; | |
| import javax.servlet.ServletRequest; | |
| import javax.servlet.ServletResponse; | |
| import javax.servlet.http.HttpServletRequest; | |
| import javax.servlet.http.HttpServletResponse; | |
| import java.io.IOException; | |
| import java.util.Arrays; | |
| /** | |
| * WhitelistUrlFilter is a configurable Servlet Filter that can prevent access to | |
| * specific URLs. The filter will ignore access to all URLs that are not specifically | |
| * whitelisted. Ignored URLs result in a HTTP 404 response. | |
| * | |
| * The filter may be used when specific files or directories should not be accessible. | |
| * In the case of executable WARs, use of this filter is highly recommended since | |
| * executable WARs must meet the requirements of both JAR and WAR files, thus placing | |
| * compiled classes and their package structure inside the document webroot. | |
| * | |
| * Sample usage: | |
| * <pre> | |
| * <filter> | |
| * <filter-name>WhitelistUrlFilter</filter-name> | |
| * <filter-class>alpine.filters.WhitelistUrlFilter</filter-class> | |
| * <init-param> | |
| * <param-name>allowUrls</param-name> | |
| * <param-value>/images,/css</param-value> | |
| * </init-param> | |
| * </filter> | |
| * | |
| * <filter-mapping> | |
| * <filter-name>WhitelistUrlFilter</filter-name> | |
| * <url-pattern>/*</url-pattern> | |
| * </filter-mapping> | |
| * | |
| * </pre> | |
| * | |
| * Optionally, the forwardTo parameter can be specified to instruct the | |
| * WhitelistUrlFilter to forward the request to a URL of another Servlet, | |
| * JSP, or HTML file should the originally requested URL not be whitelisted. | |
| * This may be necessary in some Single Page Applications (SPA). | |
| * | |
| * @author Steve Springett | |
| * @since 1.0.0 | |
| */ | |
| public final class WhitelistUrlFilter implements Filter { | |
| private String[] allowUrls = {}; | |
| private String[] forwardExcludes = {}; | |
| private String forwardTo = null; | |
| /** | |
| * Initialize "allowUrls" parameter from web.xml. | |
| * | |
| * @param filterConfig A filter configuration object used by a servlet container | |
| * to pass information to a filter during initialization. | |
| */ | |
| public void init(final FilterConfig filterConfig) { | |
| final String allowParam = filterConfig.getInitParameter("allowUrls"); | |
| if (StringUtils.isNotBlank(allowParam)) { | |
| this.allowUrls = allowParam.split(","); | |
| } | |
| final String forwardExcludesParam = filterConfig.getInitParameter("forwardExcludes"); | |
| if (StringUtils.isNotBlank(forwardExcludesParam)) { | |
| this.forwardExcludes = forwardExcludesParam.split(","); | |
| } | |
| final String forwardToParam = filterConfig.getInitParameter("forwardTo"); | |
| if (StringUtils.isNotBlank(forwardToParam)) { | |
| this.forwardTo = forwardToParam; | |
| } | |
| } | |
| /** | |
| * Check for allowed URLs being requested. | |
| * | |
| * @param request The request object. | |
| * @param response The response object. | |
| * @param chain Refers to the {@code FilterChain} object to pass control to the next {@code Filter}. | |
| * @throws IOException a IOException | |
| * @throws ServletException a ServletException | |
| */ | |
| public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) | |
| throws IOException, ServletException { | |
| final HttpServletRequest req = (HttpServletRequest) request; | |
| final HttpServletResponse res = (HttpServletResponse) response; | |
| final String requestUri = req.getRequestURI(); | |
| if (requestUri != null) { | |
| boolean allowed = false; | |
| final String requestUrlExcludingContext = requestUri.substring(req.getContextPath().length()); | |
| for (final String url: allowUrls) { | |
| if (requestUrlExcludingContext.equals("/")) { | |
| if (url.trim().equals("/") || (url.trim().equals("/index.jsp")) || (url.trim().equals("/index.html"))) { | |
| allowed = true; | |
| } | |
| } else if (requestUrlExcludingContext.startsWith(url.trim())) { | |
| allowed = true; | |
| } | |
| } | |
| if (!allowed) { | |
| if (forwardTo != null) { | |
| for (final String url: allowUrls) { | |
| if (forwardExcludes != null && Arrays.stream(forwardExcludes).anyMatch(url::equals)) { | |
| break; | |
| } | |
| final int occurrence = requestUrlExcludingContext.indexOf(url); | |
| if (occurrence > -1) { | |
| final String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString(); | |
| final String resourceUrl = requestUrlExcludingContext.substring(occurrence) + queryString; | |
| req.getRequestDispatcher(resourceUrl).forward(request, response); | |
| return; | |
| } | |
| } | |
| req.getRequestDispatcher(forwardTo).forward(request, response); | |
| } else { | |
| res.setStatus(HttpServletResponse.SC_NOT_FOUND); | |
| } | |
| return; | |
| } | |
| } | |
| chain.doFilter(request, response); | |
| } | |
| private boolean isExcludedForwardPath(String url) { | |
| return Arrays.stream(forwardExcludes).anyMatch(url::equals); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| public void destroy() { | |
| } | |
| } |