Skip to content

Zuul 网关登录验证

🏷️ Spring Boot Zuul

使用过滤器(ZuulFilter)实现登录验证。

java
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class AuthFilter extends ZuulFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger((AuthFilter.class));

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();

        // 返回 false 则不会执行 run 方法
        // 可以根据 request 信息判断是否需要验证
        // 比如,过滤请求地址结尾为 .json 的请求
        String url = request.getRequestURI();
        if (url.endsWith(".json")) {
            return false;
        }

        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();

        LOGGER.info(String.format("send %s request to %s", request.getMethod(), request.getRequestURL().toString()));

        // 可以从 Header 中获取令牌,执行验证处理
        // 也可以获取 request 中的请求参数来验证
        // 这里只是一个简单的非空验证,正常的是执行一些解密和令牌时间是否过期之类的验证
        if (StringUtils.isBlank(request.getHeader("token"))) {
            //设置为 false 则不往下走 (不调用 api 接口)
            ctx.setSendZuulResponse(false);
            //响应一个状态码:401
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            // response.setStatus(HttpStatus.UNAUTHORIZED.value());

            // 也可以返回正常结束的请求,然后执行业务处理
            // response.setStatus(HttpStatus.OK.value());
            // response.setCharacterEncoding("utf-8");
            // ctx.setResponseBody("{\"isSuccess\":false,\"msg\":\"请先登录。\",\"ErrorCode\":401}");
        }

        return null;
    }
}

参考

  1. 《Spring Cloud 与 Docker - 微服务架构实战》
  2. 使用 Zuul 过滤器实现登录验证