springcloud网关从zuul升级到gateway

本文介绍了从Zuul迁移到Spring Cloud Gateway的过程,包括配置文件的转换,如设置服务注册、路由规则、超时时间、过滤器等。同时,详细展示了如何在Gateway中实现跨域处理和权限过滤,确保服务的安全性和可用性。
摘要由CSDN通过智能技术生成

最近由于用户数逐步上升和有了长连接的需求,再加上zuul停止更新了,干脆换成gateway。


zuul的原本配置:

配置文件:

server:
  port: 1234
#服务的名称
spring:
  servlet:
    multipart:
      max-file-size: 50MB
      max-request-size: 100MB
  application:
    name: zuul
#指定注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka:8761/eureka/
  instance:
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 30
#自定义路由映射
zuul:
  routes:
    servicea:
      path: /servicea/**
    serviceb:
      path: /serviceb/**
  host:
    connect-timeout-millis: 60000
    socket-timeout-millis: 60000
  #统一前缀
  prefix: /test
ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
#不需要鉴权的地址开头
filter:
  allowPaths: /allow1,/allow2

跨域处理:

@Component
public class FirstFilter extends ZuulFilter {

    private Logger logger = LoggerFactory.getLogger(FirstFilter.class);

    @Override
    public String filterType() {
        /*
        pre:可以在请求被路由之前调用
        route:在路由请求时候被调用
        post:在route和error过滤器之后被调用
        error:处理请求时发生错误时被调用
        * */
        // 前置过滤器
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
         优先级为0,数字越大,优先级越低
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //只过滤OPTIONS 请求
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            return true;
        }

        return false;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletResponse response = ctx.getResponse();
        HttpServletRequest request = ctx.getRequest();
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "authorization,content-type,accessToken,customerCode");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Expose-Headers", "X-forwared-port, X-forwarded-host");
        response.setHeader("Vary", "Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
        response.setHeader("Access-Control-Max-Age", "1800");
        //不再路由
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(204);
        return null;
    }
}

跨域处理为最优先的过滤器,鉴权之类的业务过滤器优先级放在后面,差不多这就是zuul的配置。

gateway配置:

配置文件:

server:
  port: 12355
#服务的名称
spring:
  servlet:
    multipart:
      max-file-size: 50MB
      max-request-size: 100MB
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
          #路由id,唯一即可
        - id: serviceaRoute
          #要转发的地址,lb代表从注册中心获取服务地址
          uri: lb://servicea/**
          #断言,根据路径判断要触发此条路由
          predicates:
            - Path=/test/servicea/**
          filters:
            #此处的意思是去掉转发路径中的前两段,也就是转发到servicea时会去掉/test/servicea/
            - StripPrefix=2
      #跨域配置
      globalcors:
        cors-configurations:
          '[/**]':
            allowCredentials: true
            allowedOrigins: "*"
            allowedHeaders: "*"
            allowedMethods: "*"
            maxAge: 3628800
      #此处建议写,当配置了多条跨域时的策略选择,默认选择第三个
      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE
#指定注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka:8761/eureka/
  instance:
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 30
ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
filter:
  allows:
    #此处填不需要鉴权的路径
    - /aaa/bbb/ccc
    - /dd/fff

关于上面default-filters的配置看这里:https://github.com/spring-cloud/spring-cloud-gateway/issues/728

代码配置:

@Slf4j
@Component
public class LoginFilter implements GlobalFilter, Ordered {

    @Autowired
    private AllowProperties allowProperties;

    @Override
    public int getOrder() {
        return 1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {

            String path = exchange.getRequest().getPath().value();

            // 验证token是否有效
            HttpHeaders headers = exchange.getRequest().getHeaders();
            String accessToken = headers.getFirst("accessToken");
            //过滤不需要鉴权的
            if (ignore(path)) {
                log.info("ignore:{}", path);
                return chain.filter(exchange);
            }
            //token为空
            if (StrUtil.isEmpty(accessToken)) {
                return emptyResponse(exchange, "need token");
            }
            //不为空
            return chain.filter(exchange);
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return chain.filter(exchange);
    }


    private Mono<Void> emptyResponse(ServerWebExchange exchange, String message) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        Result<JSONObject> result = new Result<JSONObject>();
        result.setCode(HttpStatus.UNAUTHORIZED.value());
        result.setMessage(message);
        result.setSuccess(false);
        serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
        DataBuffer bodyDataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
        serverHttpResponse.getHeaders()
                .add("Content-Type", "application/json; charset=utf-8");
        return serverHttpResponse.writeWith(Mono.just(bodyDataBuffer));
    }

    /**
     * 检查是否忽略url
     */
    private boolean ignore(String path) {
        List<String> ignoreUrl = allowProperties.getAllows();
        return allowProperties.getAllows().stream()
                .map(url -> url.replace("/**", ""))
                .anyMatch(path::startsWith);
    }

}

读取配置文件的类:

@Component
@ConfigurationProperties(prefix = "filter")
@Data
public class AllowProperties {

    private List<String> allows;

}

处理web的跨域,网上讲的很多我就不写原因了:

@Configuration
@Slf4j
public class CorsConfig {

    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();

        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        log.info("Methods:{}", JSON.toJSONString(config.getAllowedMethods()));
        log.info("Origins:{}", JSON.toJSONString(config.getAllowedOrigins()));
        log.info("Headers:{}", JSON.toJSONString(config.getAllowedHeaders()));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值