让微服务只允许来自网关的请求
一般各个微服务的请求都是通过网关转发的,但是想要让微服务只允许来自网关的请求,可以操作:
在网关中:
添加一个参数systemFrom,值为gateway,一起转发给微服务,微服务只需要判断值是不是gateway即可
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//...
//省略鉴别token的代码
//只允许通过网关访问
ServerHttpRequest req = exchange.getRequest().mutate()
.header("systemFrom", "gateway").build();
return chain.filter(exchange.mutate().request(req.mutate().build()).build());
}
@Override
public int getOrder() {
return 0;
}
}
在微服务中:
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果不是网关来的服务,都拒绝访问
String fromKey = request.getHeader("systemFrom");
if(fromKey == null || !"".equals("gateway")){
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
response.setStatus(401); //权限不足
writer.write("error");
return false;
}
//... 鉴权Token
return true;
}
}
这里的systemFrom的值,如果不安全,可以继续加密,放到redis中也是可以的
但是这样无疑会很麻烦。
第一个就是要维护这个值,同时还要让Feign调用时把值带上。
真实场景中,往往是把微服务放到各个服务器,并不会对外暴露出来的,仅仅会对网关处的服务器进行开放,因此最好的做法就是不要暴露服务,NGINX反向代理到网关,网关转发到对应的服务,真正对外提供的仅有NGINX。