Spring Cloud Gateway 3.x 获取body中的数据鉴权

发布于:2024-03-29 ⋅ 阅读:(19) ⋅ 点赞:(0)

前言

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 后查看