fix #2749 add CorsHandler

This commit is contained in:
Shinsuke Sugaya 2023-06-04 14:16:45 +09:00
parent 57474fbd16
commit 9edc268a96
7 changed files with 158 additions and 49 deletions

View file

@ -0,0 +1,25 @@
/*
* Copyright 2012-2023 CodeLibs Project and the Others.
*
* 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.
*/
package org.codelibs.fess.cors;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public abstract class CorsHandler {
public abstract void process(String origin, ServletRequest request, ServletResponse response);
}

View file

@ -0,0 +1,43 @@
/*
* Copyright 2012-2023 CodeLibs Project and the Others.
*
* 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.
*/
package org.codelibs.fess.cors;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class CorsHandlerFactory {
private static final Logger logger = LogManager.getLogger(CorsHandlerFactory.class);
protected Map<String, CorsHandler> handerMap = new HashMap<>();
public void add(final String origin, final CorsHandler handler) {
if (logger.isDebugEnabled()) {
logger.debug("Loaded {}", origin);
}
handerMap.put(origin, handler);
}
public CorsHandler get(final String origin) {
final CorsHandler handler = handerMap.get(origin);
if (handler != null) {
return handler;
}
return handerMap.get("*");
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright 2012-2023 CodeLibs Project and the Others.
*
* 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.
*/
package org.codelibs.fess.cors;
import javax.annotation.PostConstruct;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
public class DefaultCorsHandler extends CorsHandler {
protected static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
protected static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
protected static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
protected static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
protected static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
@PostConstruct
public void register() {
final CorsHandlerFactory factory = ComponentUtil.getCorsHandlerFactory();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
fessConfig.getApiCorsAllowOriginList().forEach(s -> factory.add(s, this));
}
@Override
public void process(final String origin, final ServletRequest request, final ServletResponse response) {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_METHODS, fessConfig.getApiCorsAllowMethods());
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, fessConfig.getApiCorsAllowHeaders());
httpResponse.addHeader(ACCESS_CONTROL_MAX_AGE, fessConfig.getApiCorsMaxAge());
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, fessConfig.getApiCorsAllowCredentials());
}
}

View file

@ -28,7 +28,8 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.cors.CorsHandler;
import org.codelibs.fess.cors.CorsHandlerFactory;
import org.codelibs.fess.util.ComponentUtil;
public class CorsFilter implements Filter {
@ -37,66 +38,31 @@ public class CorsFilter implements Filter {
protected static final String OPTIONS = "OPTIONS";
protected static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
protected static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
protected static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
protected static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
protected static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
protected static final String WILDCARD = "*";
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final String origin = httpRequest.getHeader("Origin");
if (StringUtil.isBlank(origin)) {
chain.doFilter(request, response);
return;
}
if (logger.isDebugEnabled()) {
logger.debug("HTTP Request: {}", httpRequest.getMethod());
}
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final String allowOrigin = getAllowOrigin(fessConfig, origin);
if (StringUtil.isNotBlank(allowOrigin)) {
if (StringUtil.isNotBlank(origin)) {
if (logger.isDebugEnabled()) {
logger.debug("allowOrigin: {}", allowOrigin);
logger.debug("HTTP Request: {}", httpRequest.getMethod());
}
final HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigin);
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_METHODS, fessConfig.getApiCorsAllowMethods());
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, fessConfig.getApiCorsAllowHeaders());
httpResponse.addHeader(ACCESS_CONTROL_MAX_AGE, fessConfig.getApiCorsMaxAge());
httpResponse.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, fessConfig.getApiCorsAllowCredentials());
final CorsHandlerFactory factory = ComponentUtil.getCorsHandlerFactory();
final CorsHandler handler = factory.get(origin);
if (handler != null) {
handler.process(origin, request, response);
if (OPTIONS.equals(httpRequest.getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
return;
if (OPTIONS.equals(httpRequest.getMethod())) {
final HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
return;
}
} else if (logger.isDebugEnabled()) {
logger.debug("No CorsHandler for {}", origin);
}
}
chain.doFilter(request, response);
}
protected String getAllowOrigin(final FessConfig fessConfig, final String origin) {
final String allowOrigin = fessConfig.getApiCorsAllowOrigin();
if (StringUtil.isBlank(allowOrigin)) {
return StringUtil.EMPTY;
}
if (WILDCARD.equals(allowOrigin)) {
return allowOrigin;
}
return fessConfig.getApiCorsAllowOriginList().stream().filter(s -> s.equals(origin)).findFirst().orElse(StringUtil.EMPTY);
}
}

View file

@ -27,6 +27,7 @@ import org.codelibs.core.crypto.CachedCipher;
import org.codelibs.core.misc.DynamicProperties;
import org.codelibs.fess.api.WebApiManagerFactory;
import org.codelibs.fess.auth.AuthenticationManager;
import org.codelibs.fess.cors.CorsHandlerFactory;
import org.codelibs.fess.crawler.client.CrawlerClientCreator;
import org.codelibs.fess.crawler.client.CrawlerClientFactory;
import org.codelibs.fess.crawler.entity.EsAccessResult;
@ -211,6 +212,8 @@ public final class ComponentUtil {
private static final String CRAWLER_STATS_HELPER = "crawlerStatsHelper";
private static final String CORS_HANDLER_FACTORY = "corsHandlerFactory";
private static IndexingHelper indexingHelper;
private static CrawlingConfigHelper crawlingConfigHelper;
@ -512,6 +515,10 @@ public final class ComponentUtil {
return getComponent(CRAWLER_STATS_HELPER);
}
public static CorsHandlerFactory getCorsHandlerFactory() {
return getComponent(CORS_HANDLER_FACTORY);
}
public static <T> T getComponent(final Class<T> clazz) {
try {
return SingletonLaContainer.getComponent(clazz);

View file

@ -9,6 +9,7 @@
<include path="fess.xml"/>
<include path="fess_ldap.xml"/>
<include path="fess_api.xml"/>
<include path="fess_cors.xml"/>
<include path="fess_dict.xml"/>
<include path="fess_job.xml"/>
<include path="fess_thumbnail.xml"/>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//DBFLUTE//DTD LastaDi 1.0//EN"
"http://dbflute.org/meta/lastadi10.dtd">
<components>
<component name="corsHandlerFactory" class="org.codelibs.fess.cors.CorsHandlerFactory">
</component>
<component name="defaultCorsHandler" class="org.codelibs.fess.cors.DefaultCorsHandler">
</component>
</components>