Spring Cloud Zuul 自定义过滤器实现安全鉴权
在微服务架构中,API 网关不仅负责请求路由和负载均衡,还承担着横切关注点的处理任务,其中最重要的功能之一就是权限控制。通过在网关层实现统一的鉴权逻辑,可以有效避免在每个业务微服务中重复编写校验代码,从而简化系统架构并提高安全性。
为什么在网关层进行过滤
如果让每个微服务独立处理身份验证和授权,会导致大量的代码冗余。虽然可以通过提取公共类库来缓解,但这依然无法从本质上解耦业务逻辑与非业务逻辑。引入 Spring Cloud Zuul 过滤器后,所有进入系统的外部请求都会先经过网关。我们可以在请求被转发到具体微服务之前,拦截并执行签名校验、权限检查等操作。这样,后端微服务只需专注于业务逻辑的实现,降低了开发和维护的复杂度。
ZuulFilter 的核心组件
要实现自定义过滤器,需要继承 ZuulFilter 类并重写其定义的四个核心方法:
- filterType():返回过滤器的类型,决定其在请求生命周期的哪个阶段执行。常用取值包括
pre(路由前)、route(路由时)、post(路由后)和error(发生错误时)。 - filterOrder():定义过滤器的执行顺序。数值越小,优先级越高。
- shouldFilter():布尔类型,指定该过滤器在什么条件下需要被执行。
- run():核心业务逻辑所在,用于定义具体的拦截或处理规则。
实战演练:实现 Token 校验过滤器
以下示例展示了如何创建一个名为 TokenValidationFilter 的过滤器,用于检查请求头中是否包含合法的 X-Auth-Token。
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
public class TokenValidationFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(TokenValidationFilter.class);
@Override
public String filterType() {
// 设置为前置过滤器,在路由之前校验
return "pre";
}
@Override
public int filterOrder() {
// 设置执行优先级
return 1;
}
@Override
public boolean shouldFilter() {
// 对所有请求生效
return true;
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
logger.info("正在处理请求: {} {}", request.getMethod(), request.getRequestURL().toString());
// 从 Header 中获取校验令牌
String securityToken = request.getHeader("X-Auth-Token");
if (securityToken == null || securityToken.isEmpty()) {
logger.warn("鉴权失败:请求头中缺失 token");
// 拒绝路由该请求
context.setSendZuulResponse(false);
context.setResponseStatusCode(401);
context.setResponseBody("{\"error\": \"Unauthorized access - Token is missing\"}");
context.getResponse().setContentType("application/json;charset=UTF-8");
return null;
}
logger.info("鉴权通过");
return null;
}
}
配置与启用过滤器
编写完过滤器逻辑后,需要在 Spring Boot 的配置类中将其声明为一个 Bean,以便 Zuul 能够识别并将其加载到过滤链中。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewaySecurityConfig {
@Bean
public TokenValidationFilter tokenValidationFilter() {
return new TokenValidationFilter();
}
}
功能验证
完成配置并启动网关服务后,可以通过以下场景测试过滤器的有效性:
- 无 Token 请求:直接访问网关代理的接口,系统应返回 HTTP 401 状态码,并提示 token 缺失。
- 携带 Token 请求:在请求头中添加
X-Auth-Token: some_value再次发起请求,网关应正常转发请求至目标微服务并返回预期数据。