Jhipster微服务:Zuul代理访问控制:在端点上过滤未经授权的访问

问题描述 投票:1回答:2

我有一套Jhipster微服务,Consul和一个网关(我们称之为Gateway1),使用Keycloak / OAuth2SSO进行身份验证。我想启用多个网关(每个网关服务单独的应用程序),并为现有网关(Gateway1)提供额外的网关(Gateway2,Gateway3等)代理身份验证请求。

我尝试将以下路由添加到Gateway1来处理这个问题;

zuul: # those values must be configured depending on the application specific needs
sensitive-headers: Cookie,Set-Cookie #see https://github.com/spring-cloud/spring-cloud-netflix/issues/3126
host:
    max-total-connections: 1000
    max-per-route-connections: 100
semaphore:
    max-semaphores: 500
ignoredServices: 'consul, Gateway1' # Prevent Consul and the "Gateway1" app itself from having a Zuul route automatically created for them
routes:
   Gateway1-uaa:
      path: /api/account/**
      serviceId: Gateway1
      sensitive-headers:

一旦我将此路由添加到Gateway1,我在进行身份验证后会收到以下错误:

访问控制:在端点/ api /帐户上过滤未经授权的访问

当我点击/ api / authenticate时,它会返回我的用户。所以我怀疑通过代理传递令牌是一个问题?

我试过设置以下内容但没有成功

  • ignoredServices to *,
  • 敏感标题为空,
  • ignore-security-headers为false。
  • 禁用csrf添加.permitAll
  • 到api /帐户路线和api / **

为什么这可能不起作用的任何想法?

UPDATE

我发现错误是由我的项目中的AccessControl类抛出的(它是一个Jhipster生成的项目,因此不熟悉所有代码)。

路线是api / account / **,呼叫是api / account。在过滤器中检查它是否应该从授权列表中过滤端点并具有以下代码;

          // If this route correspond to the current request URI
        // We do a substring to remove the "**" at the end of the route URL
        if (requestUri.startsWith(serviceUrl.substring(0, serviceUrl.length() - 3))) {
            return !isAuthorizedRequest(serviceUrl, serviceName, requestUri);
        }

那么requestUri.startsWith在字符串是完全匹配时返回false(api / account vs api / account。我假设它在期待/最后。我将不得不返回并使用api / account / *进行测试看看这段代码是否会按预期工作。

现在我将它修改为3个空格但我现在似乎是在进行单个api /帐户呼叫时反复DDoSing服务 -

com.netflix.zuul.exception.ZuulException: Filter threw Exception
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:227)
    at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157)
    at com.netflix.zuul.FilterProcessor.error(FilterProcessor.java:105)
    at com.netflix.zuul.ZuulRunner.error(ZuulRunner.java:112)
    at com.netflix.zuul.http.ZuulServlet.error(ZuulServlet.java:145)
    at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:83)
    at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:165)
    at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequest(ZuulController.java:44)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:981)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:873)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:858)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at com.st.aperture.gateway.config.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:41)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:117)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:106)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at com.st.aperture.gateway.config.OAuth2Configuration$1.doFilterInternal(OAuth2Configuration.java:55)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:65)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:336)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.UndeclaredThrowableException: null
    at org.springframework.util.ReflectionUtils.rethrowRuntimeException(ReflectionUtils.java:354)
    at org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter.run(SendErrorFilter.java:99)
    at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:117)
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193)
    ... 119 common frames omitted
Caused by: java.io.IOException: An established connection was aborted by the software in your host machine
    at sun.nio.ch.SocketDispatcher.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:65)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
    at org.xnio.nio.NioSocketConduit.write(NioSocketConduit.java:164)
    at io.undertow.server.protocol.http.HttpResponseConduit.write(HttpResponseConduit.java:609)
    at io.undertow.conduits.ChunkedStreamSinkConduit.flush(ChunkedStreamSinkConduit.java:269)
    at org.xnio.conduits.ConduitStreamSinkChannel.flush(ConduitStreamSinkChannel.java:162)
    at io.undertow.channels.DetachableStreamSinkChannel.flush(DetachableStreamSinkChannel.java:119)
    at org.xnio.channels.Channels.flushBlocking(Channels.java:63)
    at io.undertow.servlet.spec.ServletOutputStreamImpl.close(ServletOutputStreamImpl.java:617)
    at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.close(OnCommittedResponseWrapper.java:520)
    at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:236)
    at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImplSetup(RequestDispatcherImpl.java:147)
    at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:111)
    at org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequestDispatcher.forward(HeaderWriterFilter.java:143)
    at org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter.run(SendErrorFilter.java:94)
    ... 121 common frames omitted

我想知道是否有重定向涉及到api / account或类似的路径...搜索继续!

spring spring-boot jhipster netflix-zuul
2个回答
0
投票

所以我在这个过程中学到的一些非常困难的课程 -

首先 - 如上所述,我将针对Jhipster accessControl过滤器提出一个错误,因为它在已经触发的路由上添加了另一层路由验证并过滤了良好的路由。如果您正在获得访问控制:在端点/ api /帐户上过滤未经授权的访问不再进一步 - 只需将其从网关配置中删除即可。

第二 - 我认为在我的设置中存在问题,或者通常只有zuul,如果目标路径/结果路径不正确 - 你得到500错误传递到堆栈而不是404.它可能是crsf但是这很差错误处理。因此,如果您看到“服务器终止连接”或“hystrix读取超时” - 它实际上可能是一个不正确的目标网址。

第三 - 如果API遵循完全相同的命名约定,则很容易建立循环和DDoS您自己的代理。例如,我点击gateway2 / api / account并希望它路由到gateway1 / api / account,所以我设置route:path:api / account service:gateway1 strip-prefix:false

这很好用......但是请求会返回gateway1 / api / account并重新定向AGAIN ..并且再次重新定向..并且再次直到你绊倒电路。

我最终在gateway1上更改了API的名称,它运行良好。


0
投票

所以 - 我可能会因为重命名API而Zuul在管理前缀方面做得很差而感到烦恼,我决定最好的办法是处理自定义过滤器;

  1. 删除前缀前缀,即路径前与路径不匹配的任何内容(例如,将gw / api / account发送到我的route / api / account不应发送service1 / gw / api / account。注意我的实现不会支持复杂的匹配模式,如/ api / ** / account /)
  2. 不路由“本地”请求,即只是在请求中没有服务名称时转发请求(例如,从网关调用api / account,不应该触发我/ api / account到网关路由。不是kthx Zuul的50倍。不苦。)
  3. 尽管有上述规则,允许其他请求自由路由

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORWARD_TO_KEY;

import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.context.RequestContext;
import com.st.aperture.gateway.gateway.filters.RequestRewriter;
import com.netflix.zuul.ZuulFilter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;

public class SimplePreFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(SimplePreFilter.class);
    private ZuulProperties properties;
    private Map<String, ZuulRoute> routes;
    private DiscoveryClient discovery;

    public SimplePreFilter(ZuulProperties properties, DiscoveryClient discovery) {
        this.properties = properties;
        this.discovery = discovery;
        this.routes = this.properties.getRoutes();
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {

        return true;
    }

    @Override
    public Object run() {

        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String requestUrl = ctx.getRequest().getRequestURI().toString();

        List<String> services = discovery.getServices();

        String modifiedPath = "";
        Boolean internalService = true;

        for (String service : services) {
            if (requestUrl.contains(service + "/")) {
                // if the url contains a service name, then its not local
                internalService = false;
                break;
            }
        }

        // The routes are the statically configured routes
        for (ZuulRoute zr : routes.values()) {
            // This will break support for wildcards in the middle of paths, consider improving
            String simpleRoute = zr.getPath().replace("/**", "");
            if (requestUrl.contains(simpleRoute) && zr.isStripPrefix() == false) {
                modifiedPath = requestUrl.substring(requestUrl.indexOf(simpleRoute.substring(0, 5)));
                break;
            }
        }

        if (internalService) {
            ctx.put(FORWARD_TO_KEY, requestUrl);
            log.debug("ROUTING: Local Request - " + requestUrl);
        } else if (modifiedPath != "") {
            RequestRewriter requestRewriter = new RequestRewriter(request);
            requestRewriter.setRequestURI(modifiedPath);
            ctx.setRequest(requestRewriter);
            log.debug("ROUTING: Foreign Request: " + requestUrl + " route prefix stripped to: " + modifiedPath);
        } else {
            log.debug("ROUTING: Foreign Request: " + requestUrl);
        }

        return null;
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.