在现代 web 应用中,很多时候客户端需要发送 POST 请求来提交数据给服务器,但是这个行为容易被恶意用户利用来发起 CSRF 攻击。为了避免 CSRF 攻击,我们可以使用 CSRF Token 机制来保护我们的应用程序。
CSRF 攻击
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种网络攻击方式,利用用户在与网站进行交互时的身份认证信息(如 cookie、sessionid 等),以其为凭据来向网站发起恶意请求,从而实现攻击的目的。比如,攻击者可以伪造一个页面,骗取用户点击,执行恶意操作,如转账、发邮件等。
比如下面这个例子:
假设网站 A 具有一个注销操作,链接为:http://www.a.com/exit
。
攻击者伪造了一个网页,其中包含如下代码:
<img src="http://www.a.com/exit" />
当受害者访问了这个网页时,浏览器会自动发出一个请求,来执行注销操作。由于这个请求的来源是受害者的浏览器,所以服务器将认为这个请求是合法的,从而执行注销操作。
CSRF Token 机制
为了防止 CSRF 攻击,我们可以使用 CSRF Token 机制。
CSRF Token 机制的原理是在服务器端生成一个随机字符串(Token),将这个字符串嵌入到表单中,浏览器提交表单时需要将这个 Token 一同提交到服务器端。服务器端发现没有 Token 或者 Token 不正确时,就拒绝这个请求。这样可以有效地防御 CSRF 攻击。
服务器端的实现
在服务器端,我们可以使用中间件 csurf
来实现 CSRF Token 机制。首先需要安装该中间件:
npm install csurf --save
然后在 Express.js 中使用:
const csrf = require('csurf') app.use(csrf())
这时候,csurf
中间件会在每个请求中生成一个 Token,并将这个 Token 放入响应的 Cookie 中,并将 Token 嵌入到模板中。我们可以在模板中使用表单帮助器来生成具有 Token 的表单:
<form action="/post" method="POST"> <input type="hidden" name="_csrf" value="<%= csrfToken %>" /> <input type="text" name="message" /> <button type="submit">Submit</button> </form>
以上代码会生成一个带有 CSRF Token 的表单,当用户提交表单时,Token 会自动随表单一起提交到服务器。
客户端的实现
在客户端,我们需要通过 JavaScript 代码来获取 CSRF Token,并将其添加到每个表单中。
csurf
中间件已经将 CSRF Token 放入了 Cookie 中,我们可以通过 JavaScript 代码来获取这个 Token:
const csrfToken = document.cookie.replace(/(?:(?:^|.*;\s*)_csrf\s*=\s*([^;]*).*$)|^.*$/, '$1')
然后,我们可以在每个表单中添加一个隐藏字段,来存放这个 Token:
<form action="/post" method="POST"> <input type="hidden" name="_csrf" value="<%= csrfToken %>" /> <input type="text" name="message" /> <button type="submit">Submit</button> </form>
这时候,客户端就可以自动添加 CSRF Token 到每个表单中。
示例代码
下面的例子演示了如何使用 CSRF Token 机制来保护表单提交:
-- -------------------- ---- ------- ----- ------- - ------------------ ----- ---- - ---------------- ----- ---------- - ---------------------- ----- ------------ - ------------------------ ----- --- - --------- ------------------------------- --------- ----- --- ----------------------- --------------- ------------ ----- ---- -- - ----- --------- - --------------- ---------- ------ ------ ----- -------------- -------------- ------ ------------- ------------ -------------------- -- ------ ----------- -------------- -- ------- ----------------------------- ------- ------- ------- -- -- ----------------- ----- ---- -- - -- --------------- --- --------------------- - ----------------- ---- ------- ------ - -------------- ---- -- ---------------- -- -- - ------------------- -- ------- -- ----------------------- --
在这个例子中,我们首先使用 body-parser
和 cookie-parser
中间件处理请求体和 Cookie,然后使用 csurf
中间件来生成 CSRF Token。
在 GET 请求中,我们生成一个带有 CSRF Token 的表单,当用户提交表单时,Token 会一同提交到服务器中。
在 POST 请求中,我们验证 CSRF Token 是否正确,如果不正确,就拒绝这个请求。否则,就处理这个请求。
总结
CSRF Token 机制是一种防范 CSRF 攻击的有效方式。在 Express.js 中,使用 csurf
中间件可以很方便地实现 CSRF Token 机制。注意,在客户端中,我们需要使用 JavaScript 代码手动在表单中添加 CSRF Token。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/648c302748841e9894a833f5