XSRF 防御「建议收藏」

XSRF 防御「建议收藏」#XSRF防御#需求分析XSRF又名CSRF(opensnewwindow),跨站请求伪造,它是前端常见的一种攻击方式,我们先通过一张图来认识它的攻击手段。CSRF的防御手段有很多,比如验证请求的referer,但是referer也是可以伪造的,所以杜绝此类攻击的一种方式是服务器端要求每次请求都包含一个token,这个token不在前端生成,而是在我们每次访…

大家好,又见面了,我是你们的朋友全栈君。

XSRF 又名 CSRF
(opens new window)
,跨站请求伪造,它是前端常见的一种攻击方式,我们先通过一张图来认识它的攻击手段。

xsrf

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

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

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

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

先修改 AxiosRequestConfig 的类型定义。

types/index.ts

export interface AxiosRequestConfig { 
     
  // ...
  xsrfCookieName?: string
  xsrfHeaderName?: string
}

然后修改默认配置。

defaults.ts

const defaults: AxiosRequestConfig = { 
     
  // ...
  xsrfCookieName: 'XSRF-TOKEN',

  xsrfHeaderName: 'X-XSRF-TOKEN',
}

接下来我们要做三件事:

  • 首先判断如果是配置 withCredentialstrue 或者是同域请求,我们才会请求 headers 添加 xsrf 相关的字段。

  • 如果判断成功,尝试从 cookie 中读取 xsrftoken 值。

  • 如果能读到,则把它添加到请求 headersxsrf 相关字段中。

我们先来实现同域请求的判断。

helpers/url.ts

interface URLOrigin { 
     
  protocol: string
  host: string
}


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

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
  }
}

同域名的判断主要利用了一个技巧,创建一个 a 标签的 DOM,然后设置 href 属性为我们传入的 url,然后可以获取该 DOM 的 protocolhost。当前页面的 url 和请求的 url 都通过这种方式获取,然后对比它们的 protocolhost 是否相同即可。

接着实现 cookie 的读取。

helpers/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

cookie 的读取逻辑很简单,利用了正则表达式可以解析到 name 对应的值。

最后实现完整的逻辑。

core/xhr.ts

const { 
     
  /*...*/
  xsrfCookieName,
  xsrfHeaderName
} = config

if ((withCredentials || isURLSameOrigin(url!)) && xsrfCookieName){ 
     
  const xsrfValue = cookie.read(xsrfCookieName)
  if (xsrfValue) { 
     
    headers[xsrfHeaderName!] = xsrfValue
  }
}

const instance = axios.create({ 
     
  xsrfCookieName: 'XSRF-TOKEN-D',
  xsrfHeaderName: 'X-XSRF-TOKEN-D'
})

instance.get('/more/get').then(res => { 
     
  console.log(res)
})

examples/server.js

app.use(express.static(__dirname, { 
     
  setHeaders (res) { 
     
    res.cookie('XSRF-TOKEN-D', '1234abc')
  }
}))

在访问页面的时候,服务端通过 set-cookie 往客户端种了 keyXSRF-TOKEN,值为 1234abccookie,作为 xsrftoken 值。

然后我们在前端发送请求的时候,就能从 cookie 中读出 keyXSRF-TOKEN 的值,然后把它添加到 keyX-XSRF-TOKEN 的请求 headers 中。

至此,我们实现了 XSRF 的自动防御的能力,下节课我们来实现 ts-axios 对上传和下载请求的支持。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144273.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月19日 下午9:40
下一篇 2022年5月19日 下午10:00


相关推荐

  • Cursor x GMI Cloud 零基础教程:用 Inference Engine 生成你的第一个小程序 – 详解

    Cursor x GMI Cloud 零基础教程:用 Inference Engine 生成你的第一个小程序 – 详解

    2026年3月15日
    3
  • vue 子传父

    vue 子传父子组件 1 在子组件中创建一个按钮 给按钮绑定一个点击事件 2 在响应该点击事件的函数中使用 emit 来触发一个自定义事件 并传递一个参数 this emit 中的 listenToChil 事件是绑定在父组件上的父组件在父组件中的子标签中监听该自定义事件并添加一个响应该事件的处理方法从而即可明白项目中的子传父传值问题 子组件 1 2 父组件

    2026年3月18日
    2
  • mac 安装golang2021 激活码_在线激活

    (mac 安装golang2021 激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月28日
    131
  • idea搭建javaweb环境_java怎么打开项目

    idea搭建javaweb环境_java怎么打开项目【第一步】新建项目【第二步】点击JavaEnterprise,选择Webapplication,选择已经下载好的Tomcat,选择服务的jdk【第三步】选择框架支撑【第四步】完成创建目录介绍【第五步】配置jar包和classes包,首先在WEB-INF下面新建两个文件夹,classes和lib(装载jar包的,利于使用jstl标签)【第六步】在file中找到ProjectStructure【第七步】点击Modules,选择P…

    2026年1月31日
    7
  • Floyed理解「建议收藏」

    Floyed理解「建议收藏」Floyed理解 Floyd算法的本质是动态规划,其转移方程为:f(k,i,j)=min(f(k-1,i,j),f(k-1,i,k)+f(k-1,k,j))。f(k-1,i,j)表示经过前k-1个点f(k-1,i,k)+f(k-1,k,j)表示经过k这个点f(k,i,j)表示路径除开起点i与终点j,只经过前k个点中的某些点,从i到j的最小值。计算这个值只需要考…

    2022年6月29日
    28
  • OpenClaw 龙虾必装技能(skill)指南

    OpenClaw 龙虾必装技能(skill)指南

    2026年3月12日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号