8-1、axios其他功能实现

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对上传和下载的支持

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • http://www.91ri.org/tag/fuzz-bug 通常情况下,有三种方法被广泛用来防御CSRF攻击...
    jdyzm阅读 4,246评论 0 5
  • CSRF & CORS 下面转的两篇文章分别说明了以下两个概念和一些解决方法: 1. CSRF - Cross-S...
    Elvis_zhou阅读 756评论 0 4
  • CORS 一、CORS内部机制与实现 CORS(Cross-Origin Resource Sharing,跨域资...
    fenerchen阅读 766评论 0 0
  • (一)CRSF跨站请求伪造 CSRF(Cross-site request forgery)跨站请求伪造,也被称为...
    肆意咯咯咯阅读 2,796评论 1 5
  • 持续两个月的披星赶月,特别怀念每天午餐得见阳光的时刻,友人问我你在搞什么。。。。说实话我很想用惯例的话语继续述说想...
    申一兵阅读 350评论 0 0