当前位置:网站首页>Talking about cors

Talking about cors

2022-08-10 23:32:00 ek1ng

最近有用 vue 然后调 face++的 api Do a front-end face recognition needs,其中使用了 axios 作为 http 请求库,配置浏览器 cors There are some not-so-identical problems encountered when limiting,写篇博客记录一下.

什么是 cors

跨源资源共享 (CORS)(或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源.跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的”预检”请求.在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头.

If the server is different origin,Then the browser will exist cors 限制,I can't follow that localhost:8080 请求到 face++ api of this server,So we need some measures to solve it cors 限制.

CORS 的意义是什么?Is it to add trouble to developers?

Mainly for defense CSRF,有了 cors 之后,Suppose a user accidentally clicks on a malicious site,也无法从 B 向站点 A 发送请求,because of the site A Will not configure to site B 的跨域,因此从 B The site initiates a direction A The request to the site is not allowed by the browser,The browser will detect it A There is no configuration pair in the response header for the site interface B Site cross domain,thereby intercepting the response.

简单请求和非简单请求

What are simple and non-simple requests?

I didn't just encounter it during development cors 限制的问题,I am equally weird,Why send one first option 请求,option 请求是什么,I clearly sent it post 请求.Then this is actually because the browser will CORS 请求分为两类:简单请求(simple request)和非简单请求(not-simple-request),简单请求浏览器不会预检,而非简单请求会预检.这两种方式怎么区分?

1.请求方式只能是:GET、POST、HEAD

2.HTTP 请求头限制这几种字段:Accept、Accept-Language、Content-Language、Content-Type、Last-Event-ID

3.Content-type 只能取:application/x-www-form-urlencoded、multipart/form-data、text/plain

Since when I send the request,Content-type 是 json 格式,This will trigger a non-simple request.

非简单请求是对那种对服务器有特殊要求的请求,比如请求方式是 PUT 或者 DELETE,或者 Content-Type 字段类型是 application/json.都会在正式通信之前,增加一次 HTTP 请求,称之为预检.浏览器会先询问服务器,当前网页所在域名是否在服务器的许可名单之中,服务器允许之后,浏览器会发出正式的 XMLHttpRequest 请求,否则会报错.

那这样看来,face++的 api We cannot modify the port design,So we definitely need to add Content-Type 字段,Also look carefully face++We can also find it in the documentation,确实是需要 Content-Type = multipart/form-data 的设置,我们给 axios After adding this request header,就会变成 POST 请求啦,但是我们发现 POST The request is still blocked,Because whether it is a simple request or a non-simple request,all received cors 限制的.

What is the significance of preflighting for non-simple requests?

In short, it should save resources,非简单请求就是普通 HTML Form 无法实现的请求.比如 PUT 方法、需要其他的内容编码方式、自定义头之类的.

对于服务器来说,第一,许多服务器压根没打算给跨源用.当然你不给 CORS 响应头,浏览器也不会使用响应结果,但是请求本身可能已经造成了后果.所以最好是默认禁止跨源请求.

第二,要回答某个请求是否接受跨源,可能涉及额外的计算逻辑.这个逻辑可能很简单,比如一律放行.也可能比较复杂,结果可能取决于哪个资源哪种操作来自哪个 origin.对浏览器来说,就是某个资源是否允许跨源这么简单;对服务器来说,计算成本却可大可小.所以我们希望最好不用每次请求都让服务器劳神计算.

CORS-preflight 就是这样一种机制,浏览器先单独请求一次,询问服务器某个资源是否可以跨源,如果不允许的话就不发实际的请求.注意先许可再请求等于默认禁止了跨源请求.如果允许的话,浏览器会记住,然后发实际请求,且之后每次就都直接请求而不用再询问服务器否可以跨源了.于是,服务器想支持跨源,就只要针对 preflight 进行跨源许可计算.本身真正的响应代码则完全不管这个事情.并且因为 preflight 是许可式的,也就是说如果服务器不打算接受跨源,什么事情都不用做.

但是这机制只能限于非简单请求.在处理简单请求的时候,如果服务器不打算接受跨源请求,不能依赖 CORS-preflight 机制.因为不通过 CORS,普通表单也能发起简单请求,所以默认禁止跨源是做不到的.

既然如此,简单请求发 preflight 就没有意义了,就算发了服务器也省不了后续每次的计算,反而在一开始多了一次 preflight.

Misconfigured cross-domain results

Classic misconfigurationAccess-Control-Allow-Origin = *.

首先,Cross domain itself is a security measure,This wrong cross-domain configuration is equivalent to cross-domain defense CSRF Prevent loneliness.

其次,chromium The kernel also imposes strict restrictions on backend configuration cross-domain errors,This will also cause you to encounter a lot of difficulties when developing,For example, the authentication interface of the backend passes through set-cookie 响应头返回了 session,You want to get it from the request header session 但是你拿不到,Then a lookup to find out if you want from set-cookie 里面拿 session 那就需要配置 Access-Control-Allow-Credentials 这个响应头,So, for example, if you write the front end, you use it axios,有 with credential This property can be turned on,But after opening it, cross-domain configuration is due to backend misconfiguration,Your request will be there with credential After opening, it is intercepted by cross-domain,原因是 chromium It was found that the backend was misconfigured across domains,总之,The essential problem of misconfigured cross-domain is that it cannot be defended CSRF 攻击,Therefore, the browser checks the fields of the response header after requesting a misconfigured cross-domain interface,and intercept the response,It will also make it difficult to continue working on development.

CORS 的解决方案

cors The solutions are essentially solved through proxy servers

正确配置 CORS 请求头

The backend interface is configured correctly cors 的请求头即可,But I am calling here api,So I have to figure out a way to solve this problem on the front end.

webpack 的 devServer

So what we are now making is a simple request.

对于简单请求,浏览器直接请求,会在请求头信息中,增加一个 origin 字段,来说明本次请求来自哪个源(协议+域名+端口).服务器根据这个值,来决定是否同意该请求,服务器返回的响应会多几个头信息字段.

这个时候 face++的 api The interface still doesn't agree this time http 请求,Then it's because his server doesn't have permission localhost:8080 access to this client,这时候我们需要给 vue 配置 proxy,That is, proxy requests,首先 localhost:8080 The request will be sent to the proxy server,Then the proxy server can obtain the information returned by the interface,At this time, cross-domain can be solved,Let's talk about why configuring a proxy can solve cross-domain problems.

Not a web service access proxy,Instead, the proxy detects the interface service inside the web service,When eligible services appear,A proxy server intercepts requests and requests web backend services as a proxy server,Requests between servers are not subject to cross-domain restrictions,Because cross-domain is a security policy of the browser,Then the proxy server will return the returned interface to the client at this time,客户端就不会收到 cors 的限制啦.

下面是给 vue.config.js 添加 devServer 的具体代码

devServer: {
    // development server port 8000
    port: 8000,
    proxy: {
        '/facepp/v3': {
            target: 'https://api-cn.faceplusplus.com',     // 拦截到'/facepp/v3'的,将axios中baseURL替换成target
            ws: true,                                 // proxy websockets
            // logLevel: 'debug',
            changeOrigin: true,                       // 是否跨域
        },
    }
  },

nginx 反向代理

Under local debugging,webpack Help you do the dirty work,那么打包之后,服务器上没有 webpack 了,What about the agent?

这时候可以使用 nginx,配置一下 server 就可以啦

config.conf 是 nginx 的配置文件,在其中 location /api 就是 nginx 的代理.The meaning is the same as that of the test environment,We can successfully solve both development and production environments cors 问题了.

原网站

版权声明
本文为[ek1ng]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208102229583351.html