Spring Cloud Gateway 登录拦截
Spring Cloud Gateway为Spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,鉴权是网关常用的功能,本文介绍基于Spring Cloud Gateway的登录拦截功能。
GlobalFilter为全局过滤器的标识接口,我这个拦截是针对所有服务,所以使用了全局过滤器。
实现Ordered为了告诉Gateway我这个过滤器的优先级,getOrder方法返回值越大优先级越低,越后执行。
还有要注意的是Spring Cloud Gateway底层使用的是webflux,基于响应式编程,我们也要避免代码中出现阻塞I/O的调用,所以我从Redis中取token使用的是非阻塞的ReactiveRedisTemplate。
Talk is cheap,show me the code
@Component
@Slf4j
public class TokenFilter implements GlobalFilter, Ordered {
private static final String TOKEN_HEAD = "token";
/**
* Redis中token前缀
*/
private static final String PREFIX = "CASECODE:USER:TOKEN:";
private static final long TIMEOUT = 60 * 30;
/**
* 需排除的接口
*/
private static final Set<String> exclude_path = ImmutableSet.of(
"/sep/user/login", "/sep/user/getCheckCode/"
);
@Autowired
private ReactiveRedisTemplate<String, String> redisTemplate;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return Mono.just(exchange)
.map(ServerWebExchange::getRequest)
.flatMap(serverHttpRequest -> {
String path = serverHttpRequest.getPath().toString();
log.info("path:{}",path);
// 排除不需要登录的接口
if (exclude_path.stream().anyMatch(path::contains)) {
log.info("无需登录");
return chain.filter(exchange);
}
// 从HEAD中取token
List<String> tokens = serverHttpRequest.getHeaders().get(TOKEN_HEAD);
// 无TOKEN
if (CollectionUtils.isEmpty(tokens)) {
return this.buildLoginResp(exchange);
}
String token = Iterables.getOnlyElement(tokens);
// 拼接前缀做为RedisKey
String redisKey = PREFIX + token;
return redisTemplate.opsForValue().get(redisKey)
.defaultIfEmpty(StringUtils.EMPTY)
.flatMap(user -> {
log.info("\nTOKEN:{}\nVALUE:{}", token, user);
// redis中有该用户
if (StringUtils.isNotEmpty(user)) {
return redisTemplate.expire(redisKey, Duration.of(TIMEOUT, ChronoUnit.SECONDS))
.then(chain.filter(exchange));
}
return this.buildLoginResp(exchange);
});
});
}
@Override
public int getOrder() {
return 0;
}
private Mono<Void> buildLoginResp(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
Map<String, Object> map = new HashMap<>();
map.put("code", 401);
map.put("message", "无效token");
String json = new Gson().toJson(map);
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bytes);
response.setStatusCode(HttpStatus.OK);
return response.writeWith(Flux.just(buffer));
}
}
Spring Cloud Gateway 登录拦截
https://blog.yjll.site/post/a9515f36.html