跨域问题

可以在后端接口层或nginx代理层做配置,不过只需要一处做配置,重复的话会报错。

golang gin配置

// 处理跨域请求,支持options访问
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method

		// 允许跨域,同一顶级域名的cookie共享
		c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))

		// 允许request headers中自定义参数,如果request headers中自定义参数不在当中,会引发跨域错误
		c.Header("Access-Control-Allow-Headers", "Content-Type,contenttype,AccessToken,X-CSRF-Token,Authorization,Token,x-token,x-user-id")
		
		// 允许跨域的方法
		c.Header("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT,OPTIONS")

		// 后端在 response headers 中自定义了参数,跨域允许前端拿到
		c.Header("Access-Control-Expose-Headers", "Content-Length,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Content-Type")
		
		// 允许携带根域名下的cookies
		c.Header("Access-Control-Allow-Credentials", "true")
		
		// 用来指定本次预检请求的有效期,单位为秒,,在此期间不用发出另一条预检请求
		c.Header("Access-Control-Max-Age", "3600")

		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

func Routers() *gin.Engine {
	Router := gin.Default()
	Router.Use(Cors())
}

nginx代理配置

如果后端api接口项目没配置,也可以在nginx层做配置

# 未来产业
server {
        listen 443 ssl http2;
        server_name xxx.com;  # 自己的域名,请求头中不同host分发到对应虚拟主机
        add_header Strict-Transport-Security "max-age=31536000" always;

        ssl_certificate /etc/nginx/conf.d/gkx_ssl/ssl.crt;
        ssl_certificate_key /etc/nginx/conf.d/gkx_ssl/ssl.key;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;

        client_max_body_size 1024m;

        location / {
            # 允许跨域;后端设置了,nginx就不用设置了,不然会重复报错
            add_header Access-Control-Allow-Origin $http_origin;
            add_header Access-Control-Allow-Credentials true;
            add_header Access-Control-Allow-Methods 'GET, POST, 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;
            }

            proxy_pass   http://127.168.0.3:808/;
            proxy_http_version  1.1;
            proxy_set_header    Connection "";
            proxy_set_header Host $host;
            proxy_connect_timeout 5;

            #下边是为获取真实IP所做的设置
            proxy_set_header    X-Real-IP        $remote_addr;
            proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header    HTTP_X_FORWARDED_FOR $remote_addr;
            proxy_set_header    X-Forwarded-Proto $scheme;
            proxy_redirect      default;
        }
    }

server {
        listen 80; # 监听80端口
        server_name xxx.com;  # 绑定证书的域名

        # 强制将http的URL重写成https
        return 301 https://xxx.com$request_uri;

    }

前端和后端根域名不一致时

允许跨域必须: Access-Control-Allow-Credentials = false

前端和后端根域名一致且需要携带cookie时

允许子域名携带根域名的cookie值

Access-Control-Allow-Credentials = true

前端调接口层面的设置

字段解释

1,Access-Control-Allow-Origin

必填字段,取值可以是请求时Origin字段的值,也可以是*,表示接受任意域名的请求。

2,Access-Control-Allow-Methods

必填字段,取值是逗号分隔的一个字符串,设置服务器支持的跨域请求的方法。

注意为了避免多次OPTIONS请求,返回的是所有支持的方法,逗号分隔。

3,Access-Control-Allow-Headers

可选字段,CORS请求时默认支持6个基本字段,XMLHttpRequest.getResponseHeader()方法:

Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。

如果需要支持其他Headers字段,必须在Access-Control-Allow-Headers里面指定。

4,Access-Control-Allow-Credentials

可选字段,布尔值类型,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中;如果设为true,即表示服务器允许在请求中包含Cookie,一起发给服务器。

注意该值只能设为true,如果服务器不允许浏览器发送Cookie,删除该字段即可。

5,Access-Control-Max-Age

可选字段,用来指定预检请求的有效期,单位为秒,在此期间不用发出另一条预检请求,不指定时即使用默认值,Chrome默认5秒。

常用浏览器有不同的最大值限制,Firefox上限是24小时 (即86400秒),Chrom是10分钟(即600秒)。

注意Access-Control-Max-Age设置针对完全一样的url,当url包含路径参数时,其中一个url的Access-Control-Max-Age设置对另一个url没有效果。

posted @ 2023-04-24 21:48  bhxuwei  阅读(33)  评论(0)    收藏  举报