我需要 jQuery .ajax() 的 CSRF 令牌吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9089909/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 10:18:58  来源:igfitidea点击:

Do I need a CSRF token for jQuery .ajax()?

jqueryajaxsecuritypostcsrf

提问by Nathan Waters

So I've got a basic .ajax() POST method to a PHP file.

所以我有一个基本的 .ajax() POST 方法到 PHP 文件。

What security measures do I need?

我需要什么安全措施?

A few posts around were mentioning using a hidden MD5 input field that you send via AJAX and verify in the PHP file. Is this a good enough method?

一些帖子提到使用隐藏的 MD5 输入字段,您通过 AJAX 发送并在 PHP 文件中验证。这是一个足够好的方法吗?

回答by Keith

The risk from CSRF is that an external site could send data to yours and the users browser will automatically send the authentication cookie along with it.

CSRF 的风险在于外部站点可能会将数据发送到您的站点,并且用户浏览器将自动发送身份验证 cookie。

What you need is some way for the receiving action (that your $.ajax()method is sending POST data to) to be able to check that the request has come from another page on your site, rather than an external site.

您需要的是接收操作(您的$.ajax()方法正在向其发送 POST 数据)的某种方式,以便能够检查请求是否来自您站点上的另一个页面,而不是外部站点。

There are a couple of ways to do this, but the recommended way is to add a token to the request that you can check for and that the hackers can't get to.

有几种方法可以做到这一点,但推荐的方法是向请求添加一个令牌,您可以检查该令牌并且黑客无法访问该令牌。

At its simplest:

最简单的:

  • On log on create a long random string token and save it against the user.
  • Add a parameter to the $.ajax()request that includes the token.
  • On request check that the token matches the one that you have saved for the user.
  • If the token doesn't match you have a CSRF hack.
  • 在登录时创建一个长随机字符串令牌并将其保存给用户。
  • $.ajax()包含令牌的请求添加参数。
  • 根据请求检查令牌是否与您为用户保存的令牌匹配。
  • 如果令牌不匹配,则您有 CSRF hack。

The hacker can't get to your DB and can't actually read the page you've sent to the user (unless they get an XSS attack in, but that's another problem) so can't spoof the token.

黑客无法访问您的数据库,也无法实际读取您发送给用户的页面(除非他们受到 XSS 攻击,但这是另一个问题),因此无法欺骗令牌。

All that matters with the token is that you can predict(and validate) it and that the hacker can't.

令牌的重要之处在于您可以预测(和验证)它而黑客不能

For this reason it's easiest to generate something long and random and store it in the DB, but you could build up something encrypted instead. I wouldn't just MD5 the username though - if the CSRF attackers figure out how to generate your tokens you'll be hacked.

出于这个原因,最容易生成长而随机的内容并将其存储在数据库中,但您可以构建一些加密的内容。不过,我不会只对用户名进行 MD5 处理 - 如果 CSRF 攻击者弄清楚如何生成您的令牌,您将被黑客入侵。

Another way is to store the token is in a cookie (rather than your database), as the attackers can't read or change your cookies, just cause them to be re-sent. Then you're the token in the HTTP POST data matches token in the cookie.

另一种方法是将令牌存储在 cookie(而不是您的数据库)中,因为攻击者无法读取或更改您的 cookie,只会导致它们被重新发送。那么你就是 HTTP POST 数据中的令牌匹配 cookie 中的令牌。

You can make these a lot more sophisticated, for instance a token that changes every time it's successfully used (preventing resubmission) or a token specific to the user and action, but that's the basic pattern.

您可以使这些更加复杂,例如每次成功使用时都会更改的令牌(防止重新提交)或特定于用户和操作的令牌,但这是基本模式。

回答by rook

In terms of request forgery, it doesn't matter how the client sends the request it matters how its received. The same CSRF rules apply for an ajax post as any other type of post.

在请求伪造方面,客户端如何发送请求并不重要,重要的是它如何接收。与任何其他类型的帖子一样,相同的 CSRF 规则适用于 ajax 帖子。

I recommend reading the CSRF prevention cheat sheet. Using a per-user secret token is the most common form of protection.

我建议阅读CSRF 预防备忘单。使用每个用户的秘密令牌是最常见的保护形式。

回答by SilverlightFox

No token is needed, but you should still protect any functions that change state against CSRF.

不需要令牌,但你仍然应该保护任何改变状态的函数免受 CSRF 的影响。

One simple way of doing this is adding a header that is sent with the AJAX request. No random token is needed.

一种简单的方法是添加一个与 AJAX 请求一起发送的标头。不需要随机令牌。

This works because:

这是有效的,因为:

  • HTML forms cannot have custom headers added to them by an attacker.
  • Custom headers cannot be passed cross-domain without CORS being enabled.
  • HTML 表单不能有攻击者添加的自定义标题。
  • 如果未启用 CORS,则无法跨域传递自定义标头。

Of course the server-side code needs to ensure that the header is present before executing its action.

当然,服务器端代码需要在执行其操作之前确保标头存在。

More info: What's the point of the X-Requested-With header?

更多信息:X-Requested-With 标头有什么意义?

回答by SilverlightFox

Here's a simple demo you can try with django:

这是您可以使用 django 尝试的简单演示:

On HTML page

在 HTML 页面上

{%block content%}
<form id="userForm">
{%csrf_token%}
  <input type="text" id="username" placeholder="User Name">
  <input type="password" id="password" placeholder="Password">
</form>
{%endblock%}

Java-Script Code

Java 脚本代码

%(document).on('submit','#userForm',function(e){
   e.preventDefault();

 $.ajax({

    type = 'POST',

    url:'path/to/url',

    data:{
     username:$('#username').val(),
     password:$('#password').val(),
     csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken').val()
    },

   success:function(data){
       alert('Successfull');
   }
  });

});