Kubernetes, SpringCloud, Vue出现跨域排查与解决方法 | Eddie'Blog
Kubernetes, SpringCloud, Vue出现跨域排查与解决方法

Kubernetes, SpringCloud, Vue出现跨域排查与解决方法

eddie 898 2020-08-24

版本

Kubernetes版本: 1.16.9-aliyun.1
SpringCloud版本:Hoxton.SR1

描述

1)在通 Kubernetes 上运行SpringCloud(简写 S.C)服务时候,能正常请求。
2)Vue请求S.C接口出现跨域问题。 比如 vue.baidu.com 请求 java.baidu.com

排错步骤

一、Kubernetes Ingress 开启跨域

具体参考官方:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors

在 vue.baidu.com 与 java.baidu.com 的yaml配置

metadata:
  annotations:
    nginx.ingress.kubernetes.io/cors-allow-headers: >-
      DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
    nginx.ingress.kubernetes.io/cors-allow-methods: 'PUT, GET, POST, OPTIONS'
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: 'true'
    nginx.ingress.kubernetes.io/service-weight: ''

发现依然不行。

二、构建Vue镜像时候的Nginx配置

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {

       # CORS
       add_header Access-Control-Allow-Origin *;
       add_header Access-Control-Allow-Methods 'GET, PUT, POST, DELETE, OPTIONS';
       add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

       if ($request_method = 'OPTIONS') {
        return 204;
       }

#        rewrite .* /index.html break;
        try_files $uri $uri/ /index.html;
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    location /static {
        alias   /usr/share/nginx/html/static;
        index  index.html;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

依然不行

三、代码

S.C 网关配置

备注: 如果需要考虑额外安全问题:addAllowedOrigin 指定域名
还可以使用yaml配置方式,就不用下面的配置方式。

1、自定义跨域配置

package com.test.gateway.config.Cors;

import com.test.gateway.filter.CorsResponseHeaderFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;


@Configuration
public class CustomCorsConfiguration {
    @Bean
    public CorsResponseHeaderFilter corsResponseHeaderFilter() {
        return new CorsResponseHeaderFilter();
    }

    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();

        corsConfiguration .addAllowedHeader("*");
        corsConfiguration .addAllowedMethod("*");
        corsConfiguration .addAllowedOrigin("*");
        corsConfiguration .setAllowCredentials(true);
        corsConfiguration .setMaxAge(600L);

        source.registerCorsConfiguration("/**", corsConfiguration );
        return new CorsWebFilter(source);
    }
}

2、跨域请求头过滤

package com.test.gateway.filter;

import com.google.common.net.HttpHeaders;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;

@Slf4j
public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {

    @Override
    public int getOrder() {
        return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
    }

    @Override
    @SuppressWarnings("serial")
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).then(Mono.defer(() -> {
            exchange.getResponse().getHeaders().entrySet().stream()
                    .filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
                    .filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
                            || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)))
                    .forEach(kv ->
                    {
                        kv.setValue(new ArrayList<String>() {{
                            add(kv.getValue().get(0));
                        }});
                    });

            return chain.filter(exchange);
        }));
    }
}

四、END

结合二、三 解决跨域问题