zhoutaoo / SpringCloud

基于SpringCloud2.1的微服务开发脚手架,整合了spring-security-oauth2、nacos、feign、sentinel、springcloud-gateway等。服务治理方面引入elasticsearch、skywalking、springboot-admin、zipkin等,让项目开发快速进入业务开发,而不需过多时间花费在架构搭建上。持续更新中
Apache License 2.0
8.68k stars 3.87k forks source link

网关跨域问题 #163

Open babyjun opened 4 years ago

babyjun commented 4 years ago

直接调用授权服务可以调通,走服务网关报403错误,请问老师有遇到吗?

zhoutaoo commented 4 years ago

403没权限 

------------------ 原始邮件 ------------------ 发件人: "zhoutaoo/SpringCloud" <notifications@github.com>; 发送时间: 2020年7月22日(星期三) 下午5:38 收件人: "zhoutaoo/SpringCloud"<SpringCloud@noreply.github.com>; 抄送: "Subscribed"<subscribed@noreply.github.com>; 主题: [zhoutaoo/SpringCloud] 网关跨域问题 (#163)

直接调用授权服务可以调通,走服务网关报403错误,请问老师有遇到吗?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

babyjun commented 4 years ago

在调用授权服务的时候就报错了,postman请求报错,"CSRF Token has been associated to this client" 大神能分享下交流群吗

Xiaoshenshe commented 4 years ago

在调用授权服务的时候就报错了,postman请求报错,"CSRF Token has been associated to this client" 大神能分享下交流群吗

我也遇到了,这是怎么处理的

EironnWalker commented 4 years ago

这个版本的Sping Cloud Gateway是有这个bug

package com.springboot.cloud.gateway.config;

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.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;

/**

 * Spring Cloud :Greenwich.SR1

 * Spring Cloud Gateway : 2.1.1.RELEASE

 * 此版本跨域有问题

 * 跨域时POST请求body内容为空,报跨域失败错误

 * 原因是Access-Control-Allow-Origin只允许有一个值,而响应头里有多个Origin

 * 参考:https://blog.csdn.net/zimou5581/article/details/90043178
   */
   @Component("corsResponseHeaderFilter")
   public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {

   @Override
   public int getOrder() {
       // 指定此过滤器位于NettyWriteResponseFilter之后
       // 即待处理完响应体后接着处理响应头
       return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
   }

   @Override
   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);
       }));

   }
   }
package com.springboot.cloud.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Configuration
public class CorsConfiguration {

    private static final String ALLOWED_HEADERS = "User-Agent,Origin,Cache-Control,Content-type,Date,Server,withCredentials,authorization";
    private static final String ALLOWED_METHODS = "GET, POST, PUT, DELETE, OPTIONS, HEAD";
    private static final String ALLOWED_ORIGIN = "*";
    private static final String ALLOWED_EXPOSE = "accesstoken";
    private static final String MAX_AGE = "3600";
    private static final String CACHE = "no-cache";
    private static final String EXPIRES = "-1";
    private static final String CREDENTIALS = "true";

    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (CorsUtils.isCorsRequest(request)) {
                ServerHttpResponse response = ctx.getResponse();
                HttpHeaders headers = response.getHeaders();
                headers.set("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
                headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
                headers.add("Access-Control-Allow-Credentials", CREDENTIALS);
                headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
                headers.add("Access-Control-Max-Age", MAX_AGE);
                headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
                headers.add("Access-Control-Request-Headers", ALLOWED_EXPOSE);
                headers.add("pragma", CACHE);
                headers.add("Expires", EXPIRES);
                headers.add("Cache-Control", CACHE);
                if (request.getMethod() == HttpMethod.OPTIONS) {
                    response.setStatusCode(HttpStatus.OK);
                    return Mono.empty();
                }
            }
            return chain.filter(ctx);
        };
    }
}

在调用授权服务的时候就报错了,postman请求报错,"CSRF Token has been associated to this client" 大神能分享下交流群吗

我也遇到了,这是怎么处理的

zhoutaoo commented 4 years ago

对于一般的接口前端做代理 就可以了。

charleskun commented 2 years ago

错误

我们也碰到这个问题,请问你解决的?

charleskun commented 2 years ago

gateway 网关服务直接把请求转发到其他服务上(一个上传文件的程序),403错误。请教一下,什么问题导致的。 image