美文网首页
8-1、axios其他功能实现

8-1、axios其他功能实现

作者: Eileen_1d88 | 来源:发表于2019-12-13 16:19 被阅读0次
1、withCredentials

修改类型定义:

interface AxiosRequestConfig {
  // ...
  withCredentials?: boolean
}

修改实现

export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    // method和data可能没有, 所以给出默认值
    const {
      url,
      method = 'get',
      data = null,
      headers,
      responseType,
      timeout,
      cancelToken,
      withCredentials
    } = config
     // ...
    if (withCredentials) {
      request.withCredentials = withCredentials
    }
  })
}
2、CSRF防御

CSRF的防御手段有很多,比如验证请求的referer,但是referer是可以伪造的,所以杜绝此类攻击的一种方式是服务器要求每次请求都包含一个token,这个token不在前端生成,而是在我们每次访问站点的时候生成,并通过set-cookie的方式保存在客户端,然后客户端发送请求的时候,从cookie中对应的字段独处token,然后添加到请求headers中。这样服务器就可以从请求headers中读取这个token并验证。由于这个token是很难伪造的,所以就能区分这个请求是否是用户正常发起的。

对于我们的ta-axios库,我们要自动把这几件事做了,每次发送请求的时候,从cookie中读取对应的token值,然后添加到请求headers中。我们允许用户配置xsrfCookieName表示存储token的cookie名称,xsrfHeaderName表示请求headers中token对应的header名称。

axios.get('/more/get',{
  xsrfCookieName: 'XSRF-TOKEN', // default
  xsrfHeaderName: 'X-XSRF-TOKEN' // default
}).then(res => {
  console.log(res)
})

我们提供xsrfCookieName和xsrfHeaderName的默认值,当然用户也可以根据自己的需求在请求中去配置xsrfCookieName和xsrfHeaderName。

代码实现
  • 修改定义
interface AxiosRequestConfig {
  //...
  xsrfCookieName?: string,
  xsrfHeaderName?: string
}
  • 修改默认配置
const defaults: AxiosRequestConfig = {
  // ...
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN'
}

接下来我们要做3件事
1、首先判断如果配置withCredentials为true或者是同源请求,我们才会在请求headers中添加xsrf相关字段;
2、如果判断成功,尝试从cookie中读取xsrf的token值;
3、如果能读到,则把它添加到请求headers的xsrf的相关字段中。

  • 同源判断
    helpers/url.ts
interface URLOrigin {
  protocol: string,
  host: string
}

const urlParsingNode = document.createElement('a')
const currentOrigin = resolveURL(window.location.href)

function resolveURL(url: string): URLOrigin {
  urlParsingNode.setAttribute('href', url)
  const { protocol, host } = urlParsingNode
  return {
    protocol,
    host
  }
}

function isURLSameOrigin(requestURL: string): boolean {
  const parsedOrigin = resolveURL(requestURL)
  return currentOrigin.protocol === parsedOrigin.protocol && currentOrigin.host === parsedOrigin.host

}
  • cookie获取
    cookie.ts
const cookie = {
  read(name: string): string | null {
    const match = document.cookie.match(new RegExp('(^|;\s*)(' + name + ')(=[^;]*)'))
    return match ? decodeURIComponent(match[3]) : null
  }
}
export default cookie

修改xhr.ts

export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    const {
       // ...
      xsrfCookieName,
      xsrfHeaderName
    } = config
    //...
    if ((withCredentials || isURLSameOrigin(url!)) && xsrfCookieName) {
      const xsrfValue = cookie.read(xsrfCookieName)
      headers[xsrfHeaderName!] = xsrfValue
    }
    // ...
  })
}
demo
import axios, { Canceler } from '../../src/index'
const instance = axios.create({
  xsrfCookieName: 'XSRF-TOKEN-D',
  xsrfHeaderName: 'X-XSRF-TOKEN-D'
})

instance.post('/api/extend/post').then(res => {
  console.log(res)
})

至此,我们实现了XSRF防御相关功能。接下来我们来实现ts-axios对上传和下载的支持

相关文章

网友评论

      本文标题:8-1、axios其他功能实现

      本文链接:https://www.haomeiwen.com/subject/maptnctx.html