spring cloud zuul网关的做用

zuul通常有两大做用,1是相似于Nginx的网址重定向,但zuul的重定向的通常是整个spring cloud里在Eureka注册中心的模块.spring

zuul:
  ignored-services: '*'
  sensitiveHeaders: Access-Control-Allow-Origin
  ignored-headers: Access-Control-Allow-Credentials,Access-Control-Allow-Origin,Vary,X-Frame-Options,token
  routes:
    oauth:
      path: /api-o/**
      serviceId: oauth-center
    api-u:
      path: /api-u/**
      serviceId: user-center
    backend:
      path: /api-b/**
      serviceId: manage-backend
    log:
      path: /api-l/**
      serviceId: log-center
    file:
      path: /api-f/**
      serviceId: file-center
    sms:
      path: /api-n/**
      serviceId: notification-center

**的意思是能够匹配任何多级目录的意思.api

*为单级目录跨域

sensitiveHeaders过滤客户端附带的headers,如:缓存

sensitiveHeaders: X-ABC
若是在发请求时带了X-ABC,那么X-ABC不会往下游服务传递。此处为禁止跨域请求头向下传递服务器

ignored-headers会过滤服务之间通讯附带的headerscookie

附带服务的跨域配置app

/**
 * 跨域配置
 */
@Configuration
public class CrossDomainConfig {

    /**
     * 跨域支持
     *
     * @return
     */
    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 容许cookies跨域
        config.addAllowedOrigin("*");// #容许向该服务器提交请求的URI,*表示所有容许
        config.addAllowedHeader("*");// #容许访问的头信息,*表示所有
        config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
        config.addAllowedMethod("*");// 容许提交请求的方法,*表示所有容许
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

二、zuul更重要的功能为过滤请求.cors

public class AccessFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return null;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        return null;
    }
}

咱们自定义一个过滤类,继承于ZuulFilter,通常要实现上面四个方法.ide

filterType:过滤器的类型.微服务

  • pre:能够在请求被路由以前调用
  • route:在路由请求时候被调用
  • post:在route和error过滤器以后被调用
  • error:处理请求时发生错误时被调用

org.springframework.cloud.netflix.zuul.filters.support.FilterConstants

中有这四种对应

public static final String ERROR_TYPE = "error";
public static final String POST_TYPE = "post";
public static final String PRE_TYPE = "pre";
public static final String ROUTE_TYPE = "route";

filterOrder:过滤器的执行顺序.当请求在一个阶段存在多个过滤器时,须要根据该方法返回的值来依次执行.

shouldFilter:判断该过滤器是否须要执行.

好比咱们须要一个过滤条件,当包含"*-anon/internal*"的uri不容许外网经过网关调用,只容许微服务间在内网调用.咱们能够这么写.

@Override
public boolean shouldFilter() {
   RequestContext requestContext = RequestContext.getCurrentContext();
   HttpServletRequest request = requestContext.getRequest();

   return PatternMatchUtils.simpleMatch("*-anon/internal*", request.getRequestURI());
}

最后就是run:过滤器的具体逻辑.

@Override
public Object run() {
   RequestContext requestContext = RequestContext.getCurrentContext();
   requestContext.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
   requestContext.setResponseBody(HttpStatus.FORBIDDEN.getReasonPhrase());
   requestContext.setSendZuulResponse(false);

   return null;
}

返回403 Forbidden错误,经过requestContext.setSendZuulResponse(false)不进行路由.

请注意以上是只防外网的,内网的调用可使用feign.好比说

@FeignClient("manage-backend")
public interface BackendClient {

   @GetMapping("/backend-anon/internal/blackIPs")
   Set<String> findAllBlackIPs(@RequestParam("params") Map<String, Object> params);
}

它是指向manage-backend模块的,并且@GetMapping("/backend-anon/internal/blackIPs")包含了"*-anon/internal*",即外网没法访问这个接口.具体实现为

@RestController
public class BlackIPController {

   @Autowired
   private BlackIPService blackIPService;

   /**
    * 添加黑名单ip
    * 
    * @param ip
    */
   @LogAnnotation(module = LogModule.ADD_BLACK_IP)
   @PreAuthorize("hasAuthority('ip:black:save')")
   @PostMapping("/blackIPs")
   public void save(@RequestBody BlackIP blackIP) {
      blackIP.setCreateTime(new Date());

      blackIPService.save(blackIP);
   }

   /**
    * 删除黑名单ip
    * 
    * @param ip
    */
   @LogAnnotation(module = LogModule.DELETE_BLACK_IP)
   @PreAuthorize("hasAuthority('ip:black:delete')")
   @DeleteMapping("/blackIPs/{ip}")
   public void delete(@PathVariable String ip) {
      blackIPService.delete(ip);
   }

   /**
    * 查询黑名单
    * 
    * @param params
    * @return
    */
   @PreAuthorize("hasAuthority('ip:black:query')")
   @GetMapping("/blackIPs")
   public Page<BlackIP> findBlackIPs(@RequestParam Map<String, Object> params) {
      return blackIPService.findBlackIPs(params);
   }

   /**
    * 查询黑名单<br>
    * 可内网匿名访问
    * 
    * @param params
    * @return
    */
   @GetMapping("/backend-anon/internal/blackIPs")
   public Set<String> findAllBlackIPs(@RequestParam Map<String, Object> params) {
      Page<BlackIP> page = blackIPService.findBlackIPs(params);
      if (page.getTotal() > 0) {
         return page.getData().stream().map(BlackIP::getIp).collect(Collectors.toSet());
      }
      return Collections.emptySet();
   }
}

中的

@GetMapping("/backend-anon/internal/blackIPs")
public Set<String> findAllBlackIPs(@RequestParam Map<String, Object> params) {
   Page<BlackIP> page = blackIPService.findBlackIPs(params);
   if (page.getTotal() > 0) {
      return page.getData().stream().map(BlackIP::getIp).collect(Collectors.toSet());
   }
   return Collections.emptySet();
}

固然它是属于manage-backend模块.

相关文章
相关标签/搜索