今天在跑本地项目时遇到一个报错:

The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

Access to XMLHttpRequest at 'http://localhost:40000/h5/getCodeQualityInfo.json' from origin 'http://localhost:4000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
createError.js:16 Uncaught (in promise) Error: Network Error
    at createError (createError.js:16)
    at XMLHttpRequest.handleError (xhr.js:117)

问题原因

Access-Control-Allow-Origin是HTML5中定义的一种解决资源跨域的策略。

他是通过服务器端返回带有Access-Control-Allow-Origin标识的Response header,用来解决资源的跨域权限问题。

使用方法

在response添加 Access-Control-Allow-Origin,例如:

Access-Control-Allow-Origin:www.google.com

www.google.com 是访问的域名,根据实际情况设置。

也可以设置为 * 表示该资源谁都可以用

Access-Control-Allow-Origin: *

如果资源是html页面,可以设置

<meta http-equiv="Access-Control-Allow-Origin" content="*">

我的服务端代码里设置了如下配置:

"Access-Control-Allow-Credentials":"true",
"Access-Control-Allow-Origin": "*",

如果服务器端开启了Access-Control-Allow-Credentials为true,假设服务器端设置了Access-Control-Allow-Origin为* 那意味这将cookie开放给了所有的网站。

假设当前是A网站,并且在cookie里写入了身份凭证 用户同时打开了B网站, 那么B网站给A网站的服务器发的所有请求都是以A用户的身份进行的, 这将导致CSRF问题。

所以正常情况下是需要设置"Access-Control-Allow-Origin"为指定网站的,我这里是本地mock所以简易写了一下。

在发起跨域请求时,如果后端已经开启CORS,前端需要也携带cookie,此时需要在前端请求头加上withCredentials: true,表示请求可以携带cookie。

在做登录认证的时候,会出现请求未登录的情况,查看请求头的时候发现并没有把登录时的cookie设置到第二次的请求头里面。查看资料才知道跨域请求要想带上cookie,必须要在ajax请求里加上xhrFields: {withCredentials: true}, crossDomain: true。

划重点:如果服务端设置了"Access-Control-Allow-Origin": "*",客户端请求时无需再设置withCredentials: true

解决办法

根据指示,将客户端请求时设置的withCredentials: true去掉即可。

const service = axios.create({
  timeout: 60 * 60 * 10,
  // withCredentials: true,
})

// axios.defaults.withCredentials = true

如果你还遇到其他跨域问题,欢迎留言交流。