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模块.