Zuul的过滤器-示例

2023-04-09 11:04:59 浏览数 (1)

下面是一个完整的示例,演示如何使用Zuul的过滤器来实现请求的验签功能。

验签逻辑

我们假设需要对所有请求进行验签,验签的逻辑如下:

  1. 获取请求参数中的signtimestamp参数。
  2. 将所有请求参数按照参数名字母升序排列,将参数值进行拼接。
  3. 将拼接后的字符串加上app_secret,然后使用MD5进行加密。
  4. 将加密后的结果和请求参数中的sign进行比较,如果相等则验签通过,否则验签失败。

实现过滤器

我们需要在pre类型的过滤器中实现验签逻辑。具体实现如下:

代码语言:javascript复制
public class SignCheckFilter extends ZuulFilter {
    private static final String SIGN_PARAM_NAME = "sign";
    private static final String TIMESTAMP_PARAM_NAME = "timestamp";
    private static final String APP_SECRET = "my_secret";

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

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

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        String sign = request.getParameter(SIGN_PARAM_NAME);
        String timestamp = request.getParameter(TIMESTAMP_PARAM_NAME);
        Map<String, String[]> paramMap = request.getParameterMap();

        if (StringUtils.isEmpty(sign) || StringUtils.isEmpty(timestamp)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseBody("Sign or timestamp is empty.");
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            return null;
        }

        String paramStr = paramMap.keySet().stream()
                .sorted()
                .filter(key -> !SIGN_PARAM_NAME.equals(key))
                .map(key -> key   "="   request.getParameter(key))
                .collect(Collectors.joining("&"));

        String expectedSign = DigestUtils.md5Hex(paramStr   APP_SECRET);
        if (!expectedSign.equals(sign)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseBody("Sign is invalid.");
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            return null;
        }

        return null;
    }
}

在上述代码中,我们首先定义了SIGN_PARAM_NAMETIMESTAMP_PARAM_NAMEAPP_SECRET三个常量,分别表示验签参数名称、时间戳参数名称和密钥。

然后在run方法中,我们获取请求中的signtimestamp参数,以及所有的请求参数。接下来,我们将所有的请求参数按照参数名字母升序排列,将参数值进行拼接,然后将拼接后的字符串加上APP_SECRET,使用MD5进行加密,得到期望的sign值。最后,我们将期望的sign值和请求中的sign进行比较,如果相等则验签通过,否则验签失败。

如果验签失败,我们会在run方法中设置SendZuulResponsefalse,表示不继续执行后面的路由和后置过滤器,直接返回响应给客户端。我们还设置了响应状态码和响应体,让客户端知道验签失败的原因。

过滤器注册

最后一步是将自定义的过滤器注册到Zuul中。我们可以在Spring Boot应用的配置文件中添加以下配置:

代码语言:javascript复制
zuul:
  routes:
    api:
      path: /api/**
      url: http://localhost:8081/
  filters:
    pre:
      signCheckFilter:
        enabled: true

在上述配置中,我们首先定义了一个路由规则,将所有以/api开头的请求转发到http://localhost:8081/。然后我们定义了一个名为signCheckFilter的过滤器,并将其设置为pre类型的过滤器,并将其启用。这样,每个进入Zuul的请求都会经过我们自定义的过滤器进行验签。

0 人点赞