不允许直接调用微服务。只允许通过 API 网关
Don't allow direct calls to Microservices. Only allow through API Gateway
也许这是一个奇怪的问题(我是微服务新手)。但是我正在寻找有关如何进行此操作的一些信息。不需要 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 端点公开的端口,并禁止任何人直接访问微服务的端口。
如果你想避免走防火墙路线,你可以强制端点检查特定的 HTTP header 或 Zuul 在转发请求之前设置的东西,但这会很麻烦容易规避。根据我过去的经验,"right" 方法是通过防火墙执行此操作。您的应用程序应负责处理请求。您的防火墙应该负责决定谁可以访问特定端点。
一般来说,这种情况是通过实施适当的 OAuth 服务器来处理的,其中只有您的 API 网关会处理令牌验证。任何对微服务的直接调用都不会进行适当的令牌交换,因此请求将被中止。
如果您已经在任何云上部署了微服务,那么您可以通过仅将路由公开给 API 网关来实现这一点。
是的,防火墙阻止、IP 白名单是限制对微服务访问的其他一些方法。
使用 AWS API 网关执行此操作的正确方法是使用最近启动的 'VPC Link' 集成,它可以保护 API 网关与您的 VPC 后端之间的连接。
使用反向代理。我们出于相同的目的使用 Nginx。 Api 网关应始终部署在生产场景的负载均衡器后面,以避免网关成为单点故障。此外,网关和服务部署在 VPC 中。
嘿,我终于找到了一个解决方案,通过使用微服务架构,只接受来自 API 网关的请求,为此你可以创建一个过滤器,像 Zuul 一样充当代理,检查 header 'X-Forwarded-Host',如果它与网关服务不匹配,则 return 一个未经授权的异常。
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);
也许这是一个奇怪的问题(我是微服务新手)。但是我正在寻找有关如何进行此操作的一些信息。不需要 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 端点公开的端口,并禁止任何人直接访问微服务的端口。
如果你想避免走防火墙路线,你可以强制端点检查特定的 HTTP header 或 Zuul 在转发请求之前设置的东西,但这会很麻烦容易规避。根据我过去的经验,"right" 方法是通过防火墙执行此操作。您的应用程序应负责处理请求。您的防火墙应该负责决定谁可以访问特定端点。
一般来说,这种情况是通过实施适当的 OAuth 服务器来处理的,其中只有您的 API 网关会处理令牌验证。任何对微服务的直接调用都不会进行适当的令牌交换,因此请求将被中止。
如果您已经在任何云上部署了微服务,那么您可以通过仅将路由公开给 API 网关来实现这一点。 是的,防火墙阻止、IP 白名单是限制对微服务访问的其他一些方法。
使用 AWS API 网关执行此操作的正确方法是使用最近启动的 'VPC Link' 集成,它可以保护 API 网关与您的 VPC 后端之间的连接。
使用反向代理。我们出于相同的目的使用 Nginx。 Api 网关应始终部署在生产场景的负载均衡器后面,以避免网关成为单点故障。此外,网关和服务部署在 VPC 中。
嘿,我终于找到了一个解决方案,通过使用微服务架构,只接受来自 API 网关的请求,为此你可以创建一个过滤器,像 Zuul 一样充当代理,检查 header 'X-Forwarded-Host',如果它与网关服务不匹配,则 return 一个未经授权的异常。
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);