CSRF 是跨站请求伪造(cross-site request forgery)的缩写;它也被称为 XSRF、一键攻击和会话劫持(session riding)。它涉及攻击者利用用户在浏览器中与某些站点建立的信任关系。攻击者通过代表用户向站点发送未经授权的命令来利用站点对用户的信任。
通常,攻击者会欺骗用户向目标站点发送请求。例如,攻击者可能能够让用户打开一个由攻击者控制的页面上的链接。这个链接可能会代表已认证用户执行某些操作,而用户对此一无所知。
考虑一个例子,用户已通过银行网站的身份验证。用户可能会被欺骗点击一个链接,该链接向其银行网站发送转账请求。由于用户已通过身份验证,银行网站会认为此交易是安全的。然而,拥有此恶意链接的攻击者将能够将转账定向到他们选择的账户。
此软件包旨在防止 Vapor 中的此类攻击。
有几种方法可以防止此类漏洞。由于攻击利用了站点对某些用户的信任,因此大多数预防技术都会向每个请求添加身份验证信息。这样做有助于站点区分授权请求和未经授权的请求。
此软件包采取的方向是使用会话(sessions)。会话将持有一个密钥(secret)。该密钥将用于创建哈希令牌(hashed token)。令牌将在响应头中发送回客户端。令牌的有效期与会话的有效期相同。
例如,服务器将生成一个令牌,并在标头中设置 "csrf-token"
键,如下所示
response.headers.add(name: "csrf-token", value: "some-very-secret-token")
然后,客户端负责在其会话期间的每个请求中发送此键和令牌。
CSRF
中间件将保证三件事
如果任何这些条件失败,则 CSRF
中间件将抛出一个错误来描述问题。
以下内容提供了关于如何在您的站点上使用此软件包的说明。
Package.swift
文件中dependencies: [
...,
.package(url: "https://github.com/vapor-community/CSRF.git", from: "3.0.0")
]
configure.swift
(或您的路由组...)中添加 SessionsMiddleware
和 CSRF
中间件app.middleware.use(app.sessions.middleware)
app.middleware.use(CSRF())
这将创建一个具有两个重要默认值的实例
ignoredMethods
将设置为 [.GET, .HEAD, .OPTIONS]
。这些方法将不会提交到上述检查。这没问题,因为这些方法不用于更改服务器状态。defaultTokenRetrieval
将设置为 ((Request) throws -> Future<String>)
。也就是说,它将是一个函数,默认情况下提供,它将接收一个 Request
并返回一个 Future<String>
,如果找到令牌,则持有该令牌;否则,该方法将抛出一个错误。您可以通过将您的首选值传递给此初始化器来定制 CSRF
上的任一属性。
router.get("test-no-session") { request in
let response = ...
response.headers.add(name: "csrf-token", value: CSRF.createToken(from: request))
return response
}
为了将此软件包与 Leaf 结合使用以保护表单,提供了一个方便的标签
configure.swift
中添加 CSRFFormFieldTag
app.leaf.tags["csrfFormField"] = CSRFFormFieldTag()
CSRFFormFieldTag
,例如像这样<form method="post">
<input type="text" name="username">
<input type="text" name="password">
[…]
#csrfFormField()
<input type="submit" value="Login">
</form>