目标:项目中使用spring boot gateway时会对服务请求进行鉴权,虽然可以在gateway服务的白名单中配置从而跳过鉴权,当可能存在某些接口不能向外暴露的情况,此时通过代码进行跳过鉴权的功能。
实现:在gateway中添加过滤器,实现GlobalFilter接口重写filter方法,并配置一个万能token(服务鉴权获取token,此时没有token,我们可以手动生成一个万能token保存起来,例如:在redis中设置一个不会过期的万能token),然后在跳转其他过滤器。
代码如下:
@Component
public class SkipAuthGlobalFilter implements GlobalFilter, Ordered {
@Resource
private RedisUtil redisUtil;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
RequestPath path = exchange.getRequest().getPath();
String s = path.toString();
if (s.contains("web/ec")) {
// 假设你的令牌通常在Authorization头中
String authorizationHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
ServerHttpRequest request = exchange.getRequest();
// 如果没有有效的令牌,分配默认令牌
String token = SnowFlake.nextId();
redisUtil.set("longToken",token);
String defaultToken = token;
ServerHttpRequest newRequest = request.mutate()
.header(HttpHeaders.AUTHORIZATION, "Bearer " + defaultToken)
.build();
ServerWebExchange build = exchange.mutate().request(newRequest).build();
return chain.filter(build);
}else {
return chain.filter(exchange);
}
} else {
// 如果不是跳过鉴权的请求,则正常进行鉴权逻辑
// 如果鉴权成功,则继续调用下一个过滤器或路由
return chain.filter(exchange);
}
}
@Override
public int getOrder() {
// 确保这个全局过滤器是在Spring Cloud Gateway的其他过滤器之前
return -30000;
}
}
上面代码中获取请求路径,判断是否包含【web/ec】如果满足条件则我们会手动赋值一个token并传入Authorization头,这里token使用雪花算法生产,具体实现可参考自己项目,使用上面提到的万能token。
赋值完成后,会重新生成一个serverHttpRequest类并转化为新的ServerWebExchange传入下一个过滤器。
getOrder方法中返回值的大小决定了过滤器执行的先后顺序
例如:我当前项目的一个过滤器是-200,这个过滤器会进行具体的鉴权
但是我这个新写的过滤器要在他之前执行,所以我的返回值就要比-200小来保证先执行我的过滤器
最后:不建议对服务请求跳过鉴权,否则没办法保证安全性,只是只对某些特定的需求进行处理。比如用户想不登录访问几个页面,此时就可以针对特定的接口跳过鉴权进行处理。