Nb
Study
.com
🔍 请输入搜索关键字

axios的withCredentials到底是什么意思?

通常我们使用以下代码创建一个axios实例。

javascript 复制代码
const axiosInstance = axios.create({
  baseURL:import.meta.env.AXIOS_BASE_URL as string,
  withCredentials: true,
  timeout: 55000,
});

那上述代码中的withCredentials 是什么意思呢?

withCredentialsXMLHttpRequest 对象的一个属性。

axios也是XMLHttpRequest的封装,当然最新的axios版本底层也支持fetch了。

withCredentials用于指示是否应该允许跨域请求携带凭据(如Cookies、HTTP认证信息、客户端SSL证明等)。当设置为 true 时,它允许跨域请求发送凭据,但同时也要求服务器端必须正确响应CORS(跨源资源共享)策略

详解 withCredentials:

1. 默认值:withCredentials 的默认值是 false。

这意味着,除非显式设置为 true,否则跨域请求不会携带凭据。

当你设置 XMLHttpRequest 的 withCredentials 属性为 true 时,你告诉浏览器在发送跨域请求时携带凭据。例如:

javascript 复制代码
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

2. 服务器端响应:

当 withCredentials 设置为 true 时,服务器必须在其CORS响应头中包含 Access-Control-Allow-Credentials: true,以允许浏览器接受带有凭据的请求。同时,Access-Control-Allow-Origin 不能设置为通配符 *,而必须指定明确的源

3. 安全性考虑:

允许跨域请求携带凭据可能会带来安全风险,因为它允许第三方网站访问敏感的用户数据。因此,只有当你完全信任目标源,并且需要在请求中包含用户凭据时,才应该将 withCredentials 设置为 true。

4. 现代浏览器和Fetch API:
在现代浏览器中,fetch API 也支持跨域请求。当使用 fetch 发起跨域请求时,可以通过设置 credentials: 'include' 来达到与 XMLHttpRequest 中 withCredentials: true 相同的效果。

七牛云前端表单直传文件提示Access-Control-Allow-Origin跨域如何解决?

使用过七牛云的小伙伴都知道,七牛云支持前端通过表单直传,只需要一个token即可。

通过如果我们使用 element plus 等UI框架自带的上传组件,只需简单配置 actiondataheader等属性即可,框架自动帮我们进行上传。

但是如果需要自定义一个文件上传组件,有可能会提示跨域。
例如,我们可以使用axios进行自定义上传:

javascript 复制代码
const axiosInstance = axios.create({
  // 问题就在这里
  withCredentials: true
  timeout: 150000,
});

const uploadFile: RequstType = async (url, params) => {
  const config = {
    headers: { "Content-Type": "multipart/form-data" },
  };
  return await axiosInstance.post(url, params,config);
};
const fd = new FormData();
// 选择的文件
fd.append("file", file);
// 后端返回的上传凭证
fd.append("token", "token");
uploadFile("https://upload.qiniup.com/",fd)

错误解读

上述代码看似没有问题,但是就是会提示跨域。

我们分析以下报错的提示:

Response to preflight request doesn't pass access control check: 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.

错误信息的意思是:

  1. Preflight request:这是一个预检请求,浏览器在发送实际请求之前,会先发送一个 OPTIONS 请求,以确定是否安全可以发送请求。
  • Access-Control-Allow-Origin header:这个响应头必须包含一个明确的允许访问的源,而不是通配符 *。
  1. The request's credentials mode is 'include':这意味着请求包含了凭据(如Cookies或HTTP认证信息),因此浏览器要求服务器明确允许来自你的源的请求。
  2. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute:这表明请求是通过 XMLHttpRequest 发起的(此处为axios),并且 withCredentials 属性被设置为 true。

解决方案

很明显,我们无法对七牛云的服务端进行配置。那只能通过前端配置 withCredentials 即可.
修改代码如下:

javascript 复制代码
const uploadFile: RequstType = async (url, params) => {
  const config = {
    headers: { "Content-Type": "multipart/form-data" },
    // 不携带cookie即可
    withCredentials: false
  };
  return await axiosInstance.post(url, params,config);
};

package.json中的overrides和resolutions字段是什么意思?

在看一些开源项目是,package.js on 中常看到overridesresolutions字段,具体是什么意思呢?
例如:

javascript 复制代码
// overrides
{
  "overrides": {
    "foo": "1.0.0"
  }
}
// overrides
"resolutions": {
  "nitropack": "link:.",
  "undici": "^6.19.2"
},

如果一个项目只依赖一个包的一个版本,只需要在package.json 的声明就可以了. 但是如果项目中同时依赖了两个不同包,而这这两个不同的包,又分别依赖的 foo 包的不同版本,这时候就涉及到需要进行版本重写(overrides/resolution)了。

术语说明:
一级依赖:直接声明在 package.json 的 (dev | optional | peer) dependencies 中的依赖。
子依赖:一级依赖的依赖,无法由应用开发者直接指定版本。
嵌套重写:指仅重写某个依赖下的一级依赖或者子依赖(限制 Scope 重写依赖版本)。

其中,npm 支持overrides字段,yarn支持 resolutions字段,pnpm 两个字段都支持,一般使用 resolutions字段。

override

对override来说,常用规则如下:

javascript 复制代码
{
  "overrides": {
    //foo is always installed as version 1.0.0 no matter what version your dependencies rely on
    "foo": "1.0.0"
    // 将 foo 替换成 dependencies 中声明的版本
    "foo": "$foo",
    // 表示仅将 1.0.0 的 foo 版本重写到 1.0.1
    "foo@1.0.0": "1.0.1", 
    // 嵌套中,用 “.“ 代表嵌套的包本身
    "foo": {
      ".": "1.0.0",
      // 重写 foo 下级所有的 bar 依赖版本至 1.0.0
      "bar": "1.0.0"
    }
  }
}

关于overrides字段详解介绍 https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides

resolutions规则

在pnpm 中 pnpm.overridesresolutions 字段的功能相同,后者是前者的别名,主要是为了兼容resolutions

nuxt 3 动态路由关键点总结

Nuxt3 本身是基于文件的路由,即根据pages目录下的文件自动进行路由。

方括号

所谓动态路由,即可以根据$route.params 获取路径中的不同参数,当你把任何文件或文件夹放置于方括号[]中时,将自动生成动态路由。

例如:

复制代码
-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue

对于上述文件结果,在模版文件中可以通过以下方式获取 groupid.

复制代码
//  pages/users-[group]/[id].vue
<template>
  <p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>

双方括号

如果你希望参数是可选的,可以使用双方括号

~/pages/[[slug]]/index.vue or ~/pages/[[slug]].vue 这两种情形,都会匹配 / and /test.

上述规则务必要好好理解。

同时,目录下的 index.vue, 默认是匹配该目录,例如~/pages/course/index.vue 会匹配 /course 路由。

捕获所有路由

如果你希望捕获所有路由,可以将文件命名为[...slug].vue 样式。

例如,对 pages/course/[...slug].vue 会同时匹配 /course/list/course/list/123 路由, 而且可以通过{{ $route.params.slug }} 获取到相关参数。

路由优先级

命名路由的优先级会高于动态路由。
例如:
对于 /foo/hello 路由, ~/pages/foo.vue 会优先于 ~/pages/foo/[slug].vue.

~/pages/foo/index.vue and ~/pages/foo/[slug].vue 会分别匹配 /foo/foo/hello.

实战

如果我们想通过/course 展示课程列表,通过/course/nuxt/course/golang 动态展示具体的课程,该如何设计路由呢?

❎ 错误的方式

复制代码
-| pages/
---| course.vue
---| course/
-----| [name].vue

因为,上述 /course/nuxt 会展示和 /course 一样的内容,即实际生成的是嵌套路由。

✅ 正确的方式

复制代码
-| pages/
---| course/
-----| index.vue
-----| [name].vue

因为,index.vue 为命名路由,优先级较高,因此 /course 会匹配 pages/course/index.vue 文件。
而, /course/nuxt 为匹配 pages/course/[name].vue 文件