diff --git a/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java b/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java index beb5a7785..6e321980e 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java @@ -44,8 +44,8 @@ public class AuthFilter implements Filter { @Autowired private SwitchDomain switchDomain; - private static ConcurrentMap methodCache = new - ConcurrentHashMap(); + @Autowired + private FilterBase filterBase; @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -61,13 +61,10 @@ public class AuthFilter implements Filter { try { String path = new URI(req.getRequestURI()).getPath(); - String target = getMethodName(path); - - Method method = methodCache.get(target); + Method method = filterBase.getMethod(req.getMethod(), path); if (method == null) { - method = mapClass(path).getMethod(target, HttpServletRequest.class, HttpServletResponse.class); - methodCache.put(target, method); + throw new NoSuchMethodException(); } if (method.isAnnotationPresent(NeedAuth.class) && !switchDomain.isEnableAuthentication()) { @@ -97,52 +94,4 @@ public class AuthFilter implements Filter { public void destroy() { } - - private Class mapClass(String path) throws NacosException { - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT)) { - return InstanceController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_SERVICE_CONTEXT)) { - return ServiceController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT)) { - return ClusterController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_OPERATOR_CONTEXT)) { - return OperatorController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CATALOG_CONTEXT)) { - return CatalogController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_HEALTH_CONTEXT)) { - return HealthController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_RAFT_CONTEXT)) { - return RaftController.class; - } - - if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_PARTITION_CONTEXT)) { - return PartitionController.class; - } - - throw new NacosException(NacosException.NOT_FOUND, "no matched controller found!"); - - } - - static protected String getMethodName(String path) throws Exception { - String target = path.substring(path.lastIndexOf("/") + 1).trim(); - - if (StringUtils.isEmpty(target)) { - throw new IllegalArgumentException("URL target required"); - } - - return target; - } } diff --git a/naming/src/main/java/com/alibaba/nacos/naming/web/DistroFilter.java b/naming/src/main/java/com/alibaba/nacos/naming/web/DistroFilter.java index e84206010..68533deb8 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/web/DistroFilter.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/web/DistroFilter.java @@ -23,13 +23,14 @@ import com.alibaba.nacos.naming.misc.UtilsAndCommons; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpMethod; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.lang.reflect.Method; import java.net.URI; +import java.security.AccessControlException; import java.util.Map; /** @@ -43,6 +44,9 @@ public class DistroFilter implements Filter { @Autowired private SwitchDomain switchDomain; + @Autowired + private FilterBase filterBase; + @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -54,6 +58,7 @@ public class DistroFilter implements Filter { HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse resp = (HttpServletResponse) servletResponse; + // request limit: String urlString = req.getRequestURI() + "?" + req.getQueryString(); Map limitedUrlMap = switchDomain.getLimitedUrlMap(); @@ -68,19 +73,15 @@ public class DistroFilter implements Filter { } try { - String path = new URI(req.getRequestURI()).getPath(); - String serviceName = req.getParameter(CommonParams.SERVICE_NAME); + Method method = filterBase.getMethod(req.getMethod(), path); - boolean isMethodWrite = - (HttpMethod.POST.name().equals(req.getMethod()) || HttpMethod.DELETE.name().equals(req.getMethod())); - - boolean isUrlInstance = - path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT); - - if (isUrlInstance && isMethodWrite && !distroMapper.responsible(serviceName)) { + if (method == null) { + throw new NoSuchMethodException(req.getMethod() + " " + path); + } + if (method.isAnnotationPresent(CanDistro.class) && !distroMapper.responsible(serviceName)) { String url = "http://" + distroMapper.mapSrv(serviceName) + req.getRequestURI() + "?" + req.getQueryString(); try { @@ -101,10 +102,18 @@ public class DistroFilter implements Filter { OverrideParameterRequestWrapper requestWrapper = OverrideParameterRequestWrapper.buildRequest(req); requestWrapper.addParameter(CommonParams.SERVICE_NAME, groupName + UtilsAndCommons.GROUP_SERVICE_CONNECTOR + serviceName); filterChain.doFilter(requestWrapper, resp); + } catch (AccessControlException e) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "access denied: " + UtilsAndCommons.getAllExceptionMsg(e)); + return; + } catch (NoSuchMethodException e) { + resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "no such api: " + e.getMessage()); + return; } catch (Exception e) { resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Server failed," + UtilsAndCommons.getAllExceptionMsg(e)); + return; } + } @Override diff --git a/naming/src/main/java/com/alibaba/nacos/naming/web/FilterBase.java b/naming/src/main/java/com/alibaba/nacos/naming/web/FilterBase.java new file mode 100644 index 000000000..32c17b8e2 --- /dev/null +++ b/naming/src/main/java/com/alibaba/nacos/naming/web/FilterBase.java @@ -0,0 +1,111 @@ +package com.alibaba.nacos.naming.web; + +import com.alibaba.nacos.naming.controllers.*; +import com.alibaba.nacos.naming.exception.NacosException; +import com.alibaba.nacos.naming.misc.UtilsAndCommons; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.annotation.PostConstruct; +import java.lang.reflect.Method; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * @author nkorange + * @since 1.0.0 + */ +@Component +public class FilterBase { + + private ConcurrentMap methodCache = new + ConcurrentHashMap<>(); + + @PostConstruct + public void init() { + initClassMethod(InstanceController.class); + initClassMethod(ServiceController.class); + initClassMethod(ClusterController.class); + initClassMethod(CatalogController.class); + initClassMethod(HealthController.class); + initClassMethod(RaftController.class); + initClassMethod(PartitionController.class); + initClassMethod(OperatorController.class); + } + + public Method getMethod(String httpMethod, String path) { + String key = httpMethod + "-->" + path; + return methodCache.get(key); + } + + private void initClassMethod(Class clazz) { + RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); + String classPath = requestMapping.value()[0]; + for (Method method : clazz.getMethods()) { + requestMapping = method.getAnnotation(RequestMapping.class); + RequestMethod[] requestMethods = requestMapping.method(); + if (requestMethods.length == 0) { + requestMethods = new RequestMethod[1]; + requestMethods[0] = RequestMethod.GET; + } + for (String methodPath : requestMapping.value()) { + methodCache.put(requestMethods[0].name() + "-->" + classPath + methodPath, method); + } + } + } + + + public Class mapClass(String path) throws NacosException { + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT)) { + return InstanceController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_SERVICE_CONTEXT)) { + return ServiceController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT)) { + return ClusterController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_OPERATOR_CONTEXT)) { + return OperatorController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CATALOG_CONTEXT)) { + return CatalogController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_HEALTH_CONTEXT)) { + return HealthController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_RAFT_CONTEXT)) { + return RaftController.class; + } + + if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_PARTITION_CONTEXT)) { + return PartitionController.class; + } + + throw new NacosException(NacosException.NOT_FOUND, "no matched controller found!"); + + } + + public String getMethodName(String path) throws Exception { + String target = path.substring(path.lastIndexOf("/") + 1).trim(); + + if (StringUtils.isEmpty(target)) { + throw new IllegalArgumentException("URL target required"); + } + + return target; + } + + public ConcurrentMap getMethodCache() { + return methodCache; + } +}