前言
SpringCloud Gateway建立在Spring Framework5、Project Reactor和Spring Boot2.0之上,使用WebFlux非阻塞API
什么是WebFlux?
官网:https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html
传统的Web框架,比如:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的。
但是
在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程。
Spring WebFlux是Spring5引入的新的响应式框架,区别于Spring MVC,它不需要依赖Servle API,它是完全异步非阻塞的,并且基于Reactor来实现响应式流程规范
SpringCloudGateway的过滤器
通过全局过滤器GlobalFilter实现对header或body信息的判断、鉴权、拦截。
通过Request Header鉴权
@Slf4j
@Component
public class HeaderFilter implements GlobalFilter {
private static final String defUsername = "admin" ;
private static final String defPassword = "12345" ;
//过滤器的优先级,数值越⼩,优先级越⾼
@Order(0)
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 方式1:通过http header获取参数
ServerHttpRequest request = exchange.getRequest();
String username = request.getHeaders().getFirst("username");
String password = request.getHeaders().getFirst("password");
String contentType = request.getHeaders().getFirst("content-type");
log.info(
"Request Header:[username:" + username + ",password:" + password + ",contentType:" + contentType
+ "]");
if (!defUsername.equals(username) || ! defPassword.equals(password)) {
//认证失败,返回401
System.out.println("当前用户未登陆,返回:" + HttpStatus.UNAUTHORIZED);
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//表⽰继续向下执⾏
return chain.filter(exchange);
}
}
通过Request Body鉴权
/**
* ReadJsonBody
* 解析body判断json中的用户名、密码是否正确
* @param exchange
* @param chain
* @return
*/
@Slf4j
@Component
public class BodyFilter implements GlobalFilter {
private static final String defUsername = "admin" ;
private static final String defPassword = "12345" ;
private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
/**
* ReadJsonBody
*
* @param exchange
* @param chain
* @return
*/
@Order(0)
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
DataBufferUtils.retain(buffer);
return Mono.just(buffer);
});
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
return ServerRequest.create(mutatedExchange, messageReaders).bodyToMono(String.class)
.flatMap(objectValue -> {
String str = "[GatewayContext]Read JsonBody:" + objectValue ;
Gson gson = new Gson();
JsonObject obj = gson.fromJson(objectValue, JsonElement.class).getAsJsonObject();
JsonElement obj_username = obj.get("username");
JsonElement obj_password = obj.get("password");
boolean isnull = obj_username == null || obj_password == null ;
if (isnull || !defUsername.equals(obj_username.getAsString()) || !defPassword.equals(obj_password.getAsString())) {
// 认证失败,返回401
log.info("{} 用户名或密码错误,返回{}",str,HttpStatus.UNAUTHORIZED);
mutatedExchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return mutatedExchange.getResponse().setComplete();
}else {
log.info("{},正确",str);
}
return chain.filter(exchange.mutate().request(mutatedRequest).build());
});
});
}
}
本文含有隐藏内容,请 开通VIP 后查看