spring boot filter 是否可以拦截其他微服务的请求?

题目描述

spring boot filter 是否可以拦截其他微服务的请求

题目来源及自己的思路

比如我现在有3个微服务,其中两个服务A/B对外提供业务能力,另外一个服务C写个拦截器(如filter)拦截A/B两个服务的所有请求,具体就是A/B所有的接口请求都经过C的如filter是否可以实现。

相关代码

@WebFilter(filterName = "authFilter", urlPatterns = "/*")
@Order(1) 
public class AuthFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader("token");
        if (token != null) {
        //    :TODO check token
            log.info("auth success");
            chain.doFilter(request, response);
        } else {
            log.err("auth failed");
        }
    }
}

你期待的结果是什么?

是否可以通过C服务的filter 对A/B两个微服务的所有接口的请求进行计数,统计一个时间段内的每个接口被访问的次数,或者对接口进行权限控制。

注:不要告诉我用SpringCloudGateway,Zuul,或者再搞个注册中心就能解决战斗。这些框架太庞大,在小系统上用就好比高射炮打蚊子一样。我希望是能通过最高效的方式,性能最佳的情况下,在尽量少的情况下(按需)引入三方件的情况下完成战斗,且我要的代码 ~ 具体实现的代码。

补充一下:以上服务都是Spring Boot 框架。

补充:20220620
通过这两天的考虑,可以在C服务上写一个接口,然后将所有的服务接口信息和权限维护的数据库中,启动的时候全部查出来,这个接口传入用户ID和接口等信息,返回该用户对该接口的使用权限。
然后在A/B服务的配置文件中配置C服务的接口地址,然后实现filter,在filter中调用该接口获取权限信息 是否可行

阅读 3.7k
4 个回答
✓ 已被采纳

遇到了和题主一样的问题,开始想抄一下gateway的源码,打开一看是webflux的响应式编程,和现有的springboot差异太大,需要搞的细节有点多,抄还不如直接用,所以放弃。转用filer实现,先拦截所有请求,在根据path前缀进行服务转发。思路还是gateway动态代理的思路,比如A服务真实接口:/order/list,C代理后的接口为:service-A/order/list,转发时去掉service-A。参考gateway的StripPrefixGatewayFilterFactory。
下面代码是本服务代理,跨服务代理换一下转发方式即可

@ServletComponentScan
@Component
public class WxPaySecurityFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse res = (HttpServletResponse) servletResponse;
        String path = req.getRequestURI();
        if (StringUtils.isNotBlank(path) && (path.startsWith("/service-A") || path.startsWith("/service-B"))) {
            String service = path.substring(1, 9);
            //TODO 鉴权、统计
            path = path.substring(9);
            String finalPath = path;
            req = new HttpServletRequestWrapper((HttpServletRequest) servletRequest) {
                @Override
                public String getRequestURI() {
                    return finalPath;
                }
            };
        }
        filterChain.doFilter(req, res);
    }
}

你希望C服务能拦截A、B两个服务的请求,而且也给出了filter,这里的filter或handler、aop是否是你想要的?

楼上+1!有没有想过网关是怎么处理你这种场景的?网关作为入口(重点),统一处理请求(这就可以拦截所有请求了),然后通过负载均衡组件,选择具体的服务实例,网关再去请求具体的业务系统接口!即使是这样,你这个网关的filter也不是拦截了业务系统的接口,还是拦截了它自己的接口!
因为这种特性,折中处理也是有的,你把filter做成公共模块,像你的ab服务,直接依赖这个模块并且配置filter,filter让他们统一去c服务做业务处理即可(oauth2.0资源服务器使用认证服务器去检验token的流程就是这种)

推荐问题