【问题标题】:Don't allow direct calls to Microservices. Only allow through API Gateway不允许直接调用微服务。只允许通过 API 网关
【发布时间】:2017-05-06 20:57:39
【问题描述】:

也许这是一个奇怪的问题(我是微服务新手)。但我正在寻找有关如何进行此操作的一些信息。不需要特定于 Spring,但这是我目前正在使用的框架。

示例: 假设我们有两个微服务

a)http://myurlfortesting.com:8085/api/rest/serviceone

b)http://myurlfortesting.com:8090/api/rest/servicetwo

我们已经设置了 Spring Zuul(充当 API 网关),其中包含转发传入调用的以下规则:

/rest/one -> http://myurlfortesting.com:8085/api/rest/serviceone

/rest/two -> http://myurlfortesting.com:8090/api/rest/servicetwo

问题... 有没有办法阻止用户直接访问 A 和 B 中提到的服务(只允许通过 API 网关来的服务)?

这可以使用 Springs Zuul(充当 API 网关)通过设置一些额外的过滤器来完成,还是我们在微服务端点中设置它?

甚至想知道是否有办法甚至不处理不通过 API 网关来的微服务端点上的直接调用。

也许这是通过服务器特定规则解决的,与 Spring 无关?

非常感谢,

/D

【问题讨论】:

  • 我会查看防火墙设置。
  • 您的 Zuul 端点是否在服务器的另一个端口上运行?假设您有防火墙,您可以将服务器的入站流量限制在您的 Zuul 端点所暴露的端口上,并禁止任何人直接访问微服务的端口。
  • @RiaanNel 端点正在服务器的另一个端口上运行。这可以通过其他方式(没有防火墙)以编程方式完成吗?
  • 您可以强制端点在转发请求之前检查特定的 HTTP 标头或 Zuul 设置的内容,但这很麻烦且容易规避。根据我过去的经验,“正确”的方法是通过防火墙来做到这一点。你的应用应该负责处理请求。你的防火墙应该负责决定谁可以访问特定的端点。
  • @RiaanNel 可以将您的评论添加为“答案”,以便我可以将其固定在您身上。认为您涵盖/验证了我的问题。谢谢!

标签: java spring rest microservices gateway


【解决方案1】:

嘿,我终于找到了一个解决方案,通过使用微服务架构仅接受来自 API 网关的请求,为此您可以创建一个过滤器,并像 Zuul 一样充当代理,检查标头“X-Forwarded-Host”,如果它与网关服务不匹配然后返回未经授权的异常。

public class CustomGatewayFilter extends GenericFilterBean {

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
        throws IOException, ServletException {

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

    String proxyForwardedHostHeader = request.getHeader("X-Forwarded-Host");

    if (proxyForwardedHostHeader == null || !proxyForwardedHostHeader.equals(GatewayConstant.getGatewayURL())) {
        UnauthorisedException unauthorisedException = new UnauthorisedException("Unauthorized Access",
                "Unauthorized Access, you should pass through the API gateway");
        byte[] responseToSend = restResponseBytes(unauthorisedException.getErrorResponse());
        ((HttpServletResponse) response).setHeader("Content-Type", "application/json");
        ((HttpServletResponse) response).setStatus(401);
        response.getOutputStream().write(responseToSend);
        return;
    }
    chain.doFilter(request, response);
}

private byte[] restResponseBytes(ErrorResponse errorResponse) throws IOException {
    String serialized = new ObjectMapper().writeValueAsString(errorResponse);
    return serialized.getBytes();
}

}

不要忘记在 SpringSecurity 配置中添加自定义过滤器

.and().addFilterBefore(new CustomGatewayFilter(), ConcurrentSessionFilter.class);

【讨论】:

【解决方案2】:

使用反向代理。我们出于同样的目的使用 Nginx。 Api 网关应始终部署在生产场景的负载均衡器后面,以避免网关成为单点故障。此外,网关和服务部署在 VPC 中。

【讨论】:

  • @MuizzMahdy “另外,网关和服务部署在 VPC 中。”
  • 对不起,我错过了。
【解决方案3】:

使用 AWS API Gateway 执行此操作的正确方法是使用最近推出的“VPC Link”集成,它可以保护 API Gateway 与 VPC 内的后端之间的连接。

https://aws.amazon.com/about-aws/whats-new/2017/11/amazon-api-gateway-supports-endpoint-integrations-with-private-vpcs/

【讨论】:

    【解决方案4】:

    通常,此类情况通过实施适当的 OAuth 服务器来处理,其中只有您的 API 网关将处理令牌验证。任何对微服务的直接调用都不会进行适当的令牌交换,因此请求将被中止。

    如果您已经在任何云上部署了微服务,那么您可以通过仅向 API 网关公开路由来实现这一目标。 是的,防火墙阻止、IP 白名单是限制对微服务的访问的其他一些方法。

    【讨论】:

      【解决方案5】:

      假设您有防火墙,您可以将服务器的入站流量限制在您的 Zuul 端点所暴露的端口上,并禁止任何人直接访问微服务的端口。

      如果您想避免使用防火墙路由,您可以强制端点在转发请求之前检查特定的 HTTP 标头或 Zuul 设置的内容,但这很麻烦并且很容易规避。根据我过去的经验,“正确”的方法是通过防火墙来做到这一点。你的应用应该负责处理请求。您的防火墙应该负责决定谁可以访问特定端点。

      【讨论】:

        猜你喜欢
        • 2023-02-03
        • 1970-01-01
        • 2021-11-13
        • 2017-01-04
        • 2019-02-15
        • 2021-03-09
        • 1970-01-01
        • 2016-02-20
        • 2021-05-03
        相关资源
        最近更新 更多