gateway 게 이 트 웨 이 인터페이스 요청 검사 방식

gateway 게 이 트 웨 이 token 검사
게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이 게 이 트 웨 이
우선 부분 필 터 를 만들어 야 합 니 다.
AbstractGateway FilterFactory 계승

그리고 apply 방법 에서 자신 이 검증 하고 자 하 는 논 리 를 실현 합 니 다.모든 요청 인자 나 token 은 request 를 통 해 얻 을 수 있 습 니 다.인증 에 실 패 했 습 니 다.catch 에서 이상 한 정 보 를 캡 처 한 다음 전단 에 요청 합 니 다.
정 보 를 되 돌려 주 는 이상 처 리 는 이 렇 습 니 다.

e.printStackTrace();
ServerHttpResponse response = exchange.getResponse();
JSONObject message = new JSONObject();
message.put("status", -1);
message.put("data", e.getMessage());
byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//    ,            
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
상태 코드 는 필요 에 따라 스스로 정의 하고 이상 정 보 는 전단 에 요청 할 수 있 습 니 다.
검사 통과 에 대해 서 는 바로 통과 시 키 면 된다.

chain.filter(exchange);
되 돌아 오 는 경 로 를 수정 해 야 한다 면 이렇게 할 수 있 습 니 다.

 //     
            String newPath ="/test/" + request.getPath();
            ServerHttpRequest newRequest = request.mutate()
                    .path(newPath)
                    .build();
            exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
            //  
            return chain.filter(exchange.mutate()
                    .request(newRequest).build());
이상 은 필터 의 작성 입 니 다.그리고 경로 의 설정 입 니 다.저 는 yml 파일 에서 설정 합 니 다.

 routes:
        - id: token_routh
          uri: lb://test-service
          order: 0
          predicates:
            - Path=/test/**
          filters:
            #   /test
            - StripPrefix=1
            - TokenApi
filers 아래 TokenApi 에 대응 하 는 필 터 는 방금 작 성 된 필터 입 니 다.지정 한 인터페이스 검사 기능 이 완료 되 었 습 니 다.
spring cloud gateway 게 이 트 웨 이 요청 처리 과정
1.게 이 트 웨 이 요청 처리 과정
  

클 라 이언 트 가 Spring Cloud Gateway 에 요청 합 니 다.게 이 트 웨 이 처리 프로그램 맵 이 경로 와 일치 하 는 지 확인 하면 게 이 트 웨 이 웹 처리 프로그램 에 보 냅 니 다.이 처리 프로그램 은 요청 한 필터 체인 을 통 해 요청 을 보 냅 니 다.필터 가 점선 으로 구 분 된 이 유 는 필터 가 프 록 시 요청 을 보 내기 전이 나 그 후에 논 리 를 수행 할 수 있 기 때문이다.모든"pre"필터 논 리 를 실행 하고 프 록 시 요청 을 합 니 다.프 록 시 요청 을 보 낸 후"post"필터 논 리 를 실행 합 니 다.
포트 가 없 는 경로 에서 정 의 된 URI 는 각각 HTTP 와 HTTPS URI 로 기본 포트 를 80 과 443 으로 설정 합 니 다.
  • DispatcherHandler:모든 요청 스케줄 러,부하 요청 배포
  • RoutePredicateHandlerMapping:서술 어 매 칭 기,경로 찾기 및 경로 찾기 후 해당 하 는 WebHandler 로 돌아 갑 니 다.Dispatcher Handler 는 Handler Mapping 집합 을 순서대로 옮 겨 다 니 며 처리 합 니 다
  • FilteringWebHandler:Filter 링크 로 요청 을 처리 하 는 WebHandler,Route Predicate Handler Mapping 으로 경 로 를 찾 은 후 해당 하 는 Filtering WebHandler 로 돌아 가 요청 을 처리 합 니 다.Filtering WebHandler 는 Filter 링크 를 조립 하고 링크 처리 요청 을 호출 합 니 다.
  • 1.1,Dispatcher Handler 배포 처리
    import org.springframework.web.reactive.dispatcherHandler 에서;클래스 중 핵심 방법 handle
    
    public Mono<Void> handle(ServerWebExchange exchange) {
            if (logger.isDebugEnabled()) {
                ServerHttpRequest request = exchange.getRequest();
                logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]");
            }
            //  handlerMapping      
            //    handlerMapping        
            //  mapping  mapping   handler,  handler  
            return this.handlerMappings == null ? Mono.error(HANDLER_NOT_FOUND_EXCEPTION) : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {
                return mapping.getHandler(exchange);
            }).next().switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)).flatMap((handler) -> {
                return this.invokeHandler(exchange, handler);
            }).flatMap((result) -> {
                return this.handleResult(exchange, result);
            });
        }
    Dispatcher Handler 의 handler 실행 순서
  • handlerMapping 검사
  • Mapping 을 옮 겨 다 니 며 mapping 에 대응 하 는 handler 를 가 져 옵 니 다.(gateway 에 대응 하 는 RoutePredicate Handler Mapping 을 찾 을 수 있 고 RoutePredicate Handler Mapping 을 통 해 handler(Filtering WebHandler)를 가 져 옵 니 다.
  • handler 에 대응 하 는 Handler Adapter 를 통 해 handler 를 호출(gateway 에서 사용 하 는 Simple Handler Adapter)즉 Filtering WebHandler 와 Simple Handler Adapter 대응

  • 그 중에서 Simple Handler Adapter 에서 handler 가 실현 되 었 습 니 다.
    
        public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
            WebHandler webHandler = (WebHandler)handler;
            Mono<Void> mono = webHandler.handle(exchange);
            return mono.then(Mono.empty());
        }
    1.2,RoutePredicateHandlerMapping 경로 서술 어 처리 맵
    
    public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
        private final FilteringWebHandler webHandler;
        private final RouteLocator routeLocator;
        public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties) {
            this.webHandler = webHandler;
            this.routeLocator = routeLocator;
            //      1,      Spring Cloud Gateway   GatewayWebfluxEndpoint    HTTP API ,       
            //    RequestMappingHandlerMapping         。RequestMappingHandlerMapping   order = 0 ,
            //      RoutePredicateHandlerMapping   。  ,RoutePredicateHandlerMapping    order = 1 。
            this.setOrder(1);
            this.setCorsConfigurations(globalCorsProperties.getCorsConfigurations());
        }
        protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
            //  mapping      
            exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR, this.getClass().getSimpleName());
            //     
            return this.lookupRoute(exchange).flatMap((r) -> {
                exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Mapping [" + this.getExchangeDesc(exchange) + "] to " + r);
                }
                //                 
                exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR, r);
                //  mapping   WebHandler FilteringWebHandler
                return Mono.just(this.webHandler);
            }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
                //           ,   GATEWAY_PREDICATE_ROUTE_ATTR
                exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR);
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("No RouteDefinition found for [" + this.getExchangeDesc(exchange) + "]");
                }
            })));
        }
        protected CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
            return super.getCorsConfiguration(handler, exchange);
        }
        private String getExchangeDesc(ServerWebExchange exchange) {
            StringBuilder out = new StringBuilder();
            out.append("Exchange: ");
            out.append(exchange.getRequest().getMethod());
            out.append(" ");
            out.append(exchange.getRequest().getURI());
            return out.toString();
        }
        protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
            //             
            return this.routeLocator.getRoutes().concatMap((route) -> {
                return Mono.just(route).filterWhen((r) -> {
                    exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
                    return (Publisher)r.getPredicate().apply(exchange);
                }).doOnError((e) -> {
                    this.logger.error("Error applying predicate for route: " + route.getId(), e);
                }).onErrorResume((e) -> {
                    return Mono.empty();
                });
            }).next().map((route) -> {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Route matched: " + route.getId());
                }
                this.validateRoute(route, exchange);
                return route;
            });
        }
        protected void validateRoute(Route route, ServerWebExchange exchange) {
        }
    }
    Route Predicate Handler Mapping 의 실행 순서
  • 경로 지정 기 를 통 해 모든 경로(RouteLocator)
  • 를 가 져 옵 니 다.
  • 경로 의 서술 어(Predicate)를 통 해 사용 할 수 없 는 경로 정보
  • 를 걸 러 냅 니 다.
  • 경로 정 보 를 찾 은 후 경로 정 보 를 컨 텍스트 환경 으로 설정 합 니 다(GATEWAYROUTE_ATTR)
  • gatway 가 정 한 webhandler(Filtering WebHandler)
  • 를 되 돌려 줍 니 다.
    비고:
    구축 방법 에서 setOrder(1)보기;역할:Spring Cloud Gateway 의 Gateway WebfluxEndpoint 는 HTTP API 를 제공 하 며 게 이 트 웨 이 를 거치 지 않 아 도 됩 니 다.
    Request Mapping Handler Mapping 을 통 해 일치 처 리 를 요청 합 니 다.Request Mapping Handler Mapping 의 order=0,Route Predicate Handler Mapping 앞 에 있어 야 하기 때문에 order=1 을 설정 합 니 다.
    1.3,FilteringWebHandler 필터 웹 요청 처리
    
    /**
     *        web      
     */
    public class FilteringWebHandler implements WebHandler {
        protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class);
        /**
         *      
         */
        private final List<GatewayFilter> globalFilters;
        public FilteringWebHandler(List<GlobalFilter> globalFilters) {
            this.globalFilters = loadFilters(globalFilters);
        }
        /**
         *           ,         GatewayFilter
         */
        private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
            return filters.stream()
                    .map(filter -> {
                        //                 
                        GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
                        //                 
                        if (filter instanceof Ordered) {
                            int order = ((Ordered) filter).getOrder();
                            //            
                            return new OrderedGatewayFilter(gatewayFilter, order);
                        }
                        return gatewayFilter;
                    }).collect(Collectors.toList());
        }
        @Override
        public Mono<Void> handle(ServerWebExchange exchange) {
            //              
            Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
            //               
            List<GatewayFilter> gatewayFilters = route.getFilters();
            //                 
            List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
            //              
            combined.addAll(gatewayFilters);
            //        
            AnnotationAwareOrderComparator.sort(combined);
            logger.debug("Sorted gatewayFilterFactories: "+ combined);
            //               
            return new DefaultGatewayFilterChain(combined).filter(exchange);
        }
    }
    Filtering WebHandler 의 실행 순서
  • 전역 필 터 를 포함 하 는 집합 구축(combined)
  • 위 아래 경로 정보 가 져 오기 GATEWAYROUTE_ATTR
  • 경로 에 있 는 필 터 를 집합 에 추가 합 니 다(combined)
  • 필터 집합 정렬 작업
  • 필터 집합 을 통 해 필터 체인 표를 조립 하고 호출 합 니 다(Default Gateway FilterChain 과 Servlet 의 FilterChain 은 원리 와 일치 합 니 다)
  • 필 터 를 통 해 구체 적 인 업무 서비스 요청 처리
  • 이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

    좋은 웹페이지 즐겨찾기