Javascript 启用Express、GraphQL和CORS的NodeJS CSRF保护

Javascript 启用Express、GraphQL和CORS的NodeJS CSRF保护,javascript,node.js,api,graphql,csrf,Javascript,Node.js,Api,Graphql,Csrf,我正在创建一个非常类似shopify的web服务,但只使用JS。启用GraphQl和Cors的API的Nodejs express。VueJS用于前端。我的身份验证正在使用JWT运行。但我有匿名结账这样的东西,所以我需要CSRF保护。问题是我的API不是路由器。我的路由器在前端,我只通过Graphql通过Axios调用API获取我需要的数据。我查看了csurf模块并进行了尝试,但目前我在前端获取CSRF令牌的方式是在API上使用/getCSRFToken端点,我已经读过,这不是一个好的实践,另一

我正在创建一个非常类似shopify的web服务,但只使用JS。启用GraphQl和Cors的API的Nodejs express。VueJS用于前端。我的身份验证正在使用JWT运行。但我有匿名结账这样的东西,所以我需要CSRF保护。问题是我的API不是路由器。我的路由器在前端,我只通过Graphql通过Axios调用API获取我需要的数据。我查看了csurf模块并进行了尝试,但目前我在前端获取CSRF令牌的方式是在API上使用/getCSRFToken端点,我已经读过,这不是一个好的实践,另一件事是,由于启用了CORS,它可以访问所有人

这是我掌握的主要信息来源:

我不知道如何准确地设置CSRF保护,而不使用am API路由来获取CSRF令牌并通过响应将其作为cookie发送,并且通常使用最佳实践来确保整个过程的安全

我也在考虑只对系统中商店的域限制对API的访问,但现在不考虑这样做是否有好处


欢迎任何建议

您可以生成cookie客户端(使用
window.crypto
),然后让JS读取并发送到标题中,服务器只需验证它们是否匹配这很容易受到cookie不是HttpOnly这一事实的影响(因为您的JS需要读取它!)。因此,这种方法不是最佳实践,但总比没有好

它也不会阻止用户从curl发出请求,一旦他们发现他们只需要提供匹配的cookie和头,但他们仍然不能代表其他用户发出请求,除非他们拥有目标用户授权凭据


实际上,使用API路由为每个请求生成一个令牌并没有什么错,尽管它确实会导致请求密度加倍(每个请求都需要一个新令牌!)。原因是攻击者无法从外部站点读取响应(CORS将阻止此操作)。这样,您就不会受到任何cookie攻击,因为您从一开始就不会存储cookie

编辑:我看到您提示启用CORS*以使此端点成为公共端点。如果您的API真的是公开的,那么您最好改用OAuth2/JWT身份验证,这样CSRF就变得无关紧要了,因为身份验证不是来自cookie

尝试跨多个请求保留值会遇到历史记录功能方面的困难,因此建议对每个请求使用令牌,或者

您还可以存储来自
getCsrfToken()
请求的cookie,并使其在一段时间内保持有效,但要使其仅为HttpOnly,因为它是由API发出的,API将负责确保它正在接收有效的CSRF令牌

以上两种方法的问题是,如果您想要真正的匿名性,那么您不能将这些令牌绑定到特定用户,因此一个用户可以通过使用自己的CSRF令牌来代表另一个用户避免CSRF检查

如果您可以想出一些方法来解决这个问题,同时保持匿名性,那么服务器可以检查它正在接收的令牌的有效性,这样一个用户就不能代表另一个用户使用他们的令牌


你的最后一个想法(假设你想要真正的匿名)可能是最好的。如果用户代理是可信的,则
referer
Origin
头不能被篡改,因此如果您乐于将API锁定到JS正在运行的域,则攻击者不会轻易绕过执行
referer
/
Origin
检查服务器端。这不是最佳做法,但实际上是有效的

同样,curl请求等可以自由发出,但只有在攻击者拥有用户授权凭据的情况下,才能代表其他用户发出



<>最后注意的是CSRF是一种替代的攻击向量,它是XSS的,但是如果你有XSS漏洞,那么CSRF防御通常会过时,所以在执行CSRF防御之前,首先要确保你先防御XSS。一个用于jwt的签名部分,该部分是安全的,另一个用于客户端读取并从中获取用户的有效负载。两者都是httpOnly和sameSite。但我不知道这与csrf保护有什么关系,因为我有一个匿名签出,我仍然需要csrf保护,而我没有通过身份验证。您能详细介绍一下OAuth2/JWT的内容吗?它是如何不使用cookies的?我的意思是,客户端是如何知道im登录的?我想知道的是,如果我在API/GetCsrToken上有一个路由,可以为im将要在客户端加载的页面获取CSRF令牌吗?如果没有,我如何向客户端获取令牌您可以将令牌存储在本地存储中而不是作为cookie,然后根据请求发送它们。如果另一个站点试图CSRF您,他们根本没有令牌,他们也无法获得令牌(浏览器将发送cookies),但如果您以这种方式存储令牌,您必须确保它们已被销毁、无效或加密。对于真正未经验证/匿名的端点,您只需将其隔离到您的域(选项3),除非您准备制作一个只能由请求用户实际使用的令牌(这很困难,因为攻击者可能也可以获得用户代理/用户IP之类的信息)来了解本地存储使用情况。。。我读过一些文章,他们说使用它存储身份验证信息不是一个好的做法,因为它不安全等等。