I asked a similar question before, and the answer was simply:
我之前问过类似的问题,答案很简单:
if JavaScript can do it, then any client can do it.
如果JavaScript可以做到,那么任何客户端都可以做到。
But I still want to find out a way do restrict AJAX calls to JavaScript.
但我仍然想找到一种限制AJAX调用JavaScript的方法。
The reason is :
原因是 :
I'm building a web application, when a user clicks on an image, tagged like this:
我正在构建一个Web应用程序,当用户点击图像时,标记如下:
<img src='src.jpg' data-id='42'/>
JavaScript calls a PHP page like this:
JavaScript调用这样的PHP页面:
$.ajax("action.php?action=click&id=42");
then action.php inserts rows in database.
然后action.php在数据库中插入行。
But I'm afraid that some users can automate entries that "clicks" all the id's and such, by calling necessary url's, since they are visible in the source code.
但我担心一些用户可以通过调用必要的url来自动化“点击”所有id等的条目,因为它们在源代码中可见。
How can I prevent such a thing, and make sure it works only on click, and not by calling the url from a browser tab?
我怎样才能阻止这样的事情,并确保它仅在点击时起作用,而不是通过从浏览器标签调用url?
p.s.
I think a possible solution would be using encryption, like generate a key on user visit, and call the action page with that key, or hash/md5sum/whatever of it. But I think it can be done without transforming it into a security problem. Am I right ? Moreover, I'm not sure this method is a solution, since I don't know anything about this kind of security, or it's implementation.
我认为一个可能的解决方案是使用加密,比如在用户访问时生成密钥,并使用该密钥调用操作页面,或使用hash / md5sum /其中任何一个。但我认为可以在不将其转化为安全问题的情况下完成。我对吗 ?此外,我不确定这种方法是否是一种解决方案,因为我对这种安全性或它的实现一无所知。
5 个解决方案
#1
2
I'm not sure there is a 100% secure answer. A combination of a server generated token that is inserted into a hidden form element and anti-automation techniques like limiting the number of requests over a certain time period is the best thing I can come up with.
我不确定是否有100%安全的答案。插入到隐藏表单元素中的服务器生成令牌和在一定时间段内限制请求数量等反自动化技术的组合是我能想到的最好的事情。
[EDIT] Actually a good solution would be to use CAPTCHAS
[编辑]实际上一个好的解决方案是使用CAPTCHAS
#2
2
Your question isn't really "How can I tell AJAX from non-AJAX?" It's "How do I stop someone inflating a score by repeated clicks and ballot stuffing?"
你的问题不是“如何从非AJAX中告诉AJAX?”这是“如何通过反复点击和选票填充来阻止某人夸大分数?”
In answer to the question you asked, the answer you quoted was essentially right. There is no reliable way to determine whether a request is being made by AJAX, a particular browser, a CURL session or a guy typing raw HTTP commands into a telnet session. We might see a browser or a script or an app, but all PHP sees is:
在回答您提出的问题时,您引用的答案基本上是正确的。没有可靠的方法来确定请求是由AJAX,特定浏览器,CURL会话还是在远程网络会话中键入原始HTTP命令的人做出的。我们可能会看到浏览器或脚本或应用程序,但所有PHP看到的是:
GET /resource.html HTTP/1.1
host:www.example.com
If there's some convenience reason for wanting to know whether a request was AJAX, some javascript libraries such as jQuery add an additional HTTP header to AJAX requests that you can look for, or you could manually add a header or include a field to your payload such as AJAX=1. Then you can check for those server side and take whatever action you think should be made for an AJAX request.
如果想要知道请求是否是AJAX有一些方便的原因,一些javascript库(如jQuery)会为您可以查找的AJAX请求添加额外的HTTP标头,或者您可以手动添加标头或在您的有效负载中包含一个字段等如AJAX = 1。然后,您可以检查那些服务器端,并采取您认为应该为AJAX请求执行的任何操作。
Of course there's nothing stopping me using CURL to make the same request with the right headers set to make the server think it's an AJAX request. You should therefore only use such tricks where whether or not the request was AJAX is of interest so you can format the response properly (send a HTML page if it's not AJAX, or JSON if it is). The security of your application can't rely on such tricks, and if the design of your application requires the ability to tell AJAX from non-AJAX for security or reliability reasons then you need to rethink the design of your application.
当然,没有什么能阻止我使用CURL来设置相同的请求,并使服务器认为它是一个AJAX请求。因此,您应该只使用这些技巧,无论请求是否是AJAX是有意义的,因此您可以正确格式化响应(如果不是AJAX则发送HTML页面,如果是,则发送JSON)。应用程序的安全性不能依赖于这些技巧,如果应用程序的设计需要能够出于安全性或可靠性的原因从非AJAX告诉AJAX,那么您需要重新考虑应用程序的设计。
In answer to what you're actually trying to achieve, there are a couple of approaches. None are completely reliable, though. The first approach is to deposit a cookie on the user's machine on first click, and to ignore any subsequent requests from that user agent if the cookie is in any subsequent requests. It's a fairly simple, lightweight approach, but it's also easily defeated by simply deleting the cookie, or refusing to accept it in the first place.
在回答您实际想要实现的目标时,有几种方法。但是,没有一个是完全可靠的。第一种方法是在第一次单击时在用户的计算机上存储cookie,如果cookie在任何后续请求中,则忽略来自该用户代理的任何后续请求。这是一种相当简单,轻量级的方法,但它也很容易通过简单地删除cookie或者首先拒绝接受它而被击败。
Alternatively, when the user makes the AJAX request, you can record some information about the requesting user agent along with the fact that a click was submitted. You can, for example store a hash (stored with something stronger than MD5!) of the client's IP and user agent string, along with a timestamp for the click. If you see a lot of the same hash, along with closely grouped timestamps, then there's possibly abuse being attempted. Again, this trick isn't 100% reliable because user agents can see any string they want as their user agent string.
或者,当用户发出AJAX请求时,您可以记录有关请求用户代理的一些信息以及提交点击的事实。例如,您可以存储客户端IP和用户代理字符串的哈希值(存储的内容比MD5强!),以及点击的时间戳。如果您看到许多相同的哈希值以及紧密分组的时间戳,那么可能会尝试滥用。同样,这个技巧不是100%可靠,因为用户代理可以看到他们想要的任何字符串作为其用户代理字符串。
#3
0
Use post method instead of get.Read the documentation here http://api.jquery.com/jQuery.post/ to learn how to use post method in jquery
使用post方法而不是get.Read文档http://api.jquery.com/jQuery.post/来学习如何在jquery中使用post方法
#4
0
You could, for example, implement a check if the request is really done with AJAX, and not by just calling the URL.
例如,您可以实现检查请求是否真的使用AJAX,而不是仅通过调用URL。
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// Yay, it is ajax!
} else {
// no AJAX, man..
}
#5
0
This solution may need more reflexion but might do the trick
这个解决方案可能需要更多的反思,但可能会有所帮助
You could use tokens as stated in Slicedpan's answer. When serving your page, you would generate uuids for each images and store them in session / database.
您可以使用Slicedpan的答案中所述的令牌。在为页面提供服务时,您将为每个图像生成uuids并将其存储在会话/数据库中。
Then serve your html as
然后将你的html服务为
<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>
Your ajax request would become
你的ajax请求会变成
$.ajax("action.php?action=click&uuid=uuidgenerated");
Then on php side, check for the uuid in your memory/database, and allow or not the transaction. (You can also check for custom headers sent on ajax as stated in other responses)
然后在php端,检查内存/数据库中的uuid,并允许或不允许该事务。 (您还可以检查ajax上发送的自定义标头,如其他响应中所述)
You would also need to purge uuids, on token lifetime, on window unload, on session expired...
你还需要在令牌生命周期,窗口卸载,会话过期时清除uuids ...
This method won't allow you to know if the request comes from an xhr but you'll be able to limit their number.
此方法不允许您知道请求是否来自xhr,但您可以限制其数量。
#1
2
I'm not sure there is a 100% secure answer. A combination of a server generated token that is inserted into a hidden form element and anti-automation techniques like limiting the number of requests over a certain time period is the best thing I can come up with.
我不确定是否有100%安全的答案。插入到隐藏表单元素中的服务器生成令牌和在一定时间段内限制请求数量等反自动化技术的组合是我能想到的最好的事情。
[EDIT] Actually a good solution would be to use CAPTCHAS
[编辑]实际上一个好的解决方案是使用CAPTCHAS
#2
2
Your question isn't really "How can I tell AJAX from non-AJAX?" It's "How do I stop someone inflating a score by repeated clicks and ballot stuffing?"
你的问题不是“如何从非AJAX中告诉AJAX?”这是“如何通过反复点击和选票填充来阻止某人夸大分数?”
In answer to the question you asked, the answer you quoted was essentially right. There is no reliable way to determine whether a request is being made by AJAX, a particular browser, a CURL session or a guy typing raw HTTP commands into a telnet session. We might see a browser or a script or an app, but all PHP sees is:
在回答您提出的问题时,您引用的答案基本上是正确的。没有可靠的方法来确定请求是由AJAX,特定浏览器,CURL会话还是在远程网络会话中键入原始HTTP命令的人做出的。我们可能会看到浏览器或脚本或应用程序,但所有PHP看到的是:
GET /resource.html HTTP/1.1
host:www.example.com
If there's some convenience reason for wanting to know whether a request was AJAX, some javascript libraries such as jQuery add an additional HTTP header to AJAX requests that you can look for, or you could manually add a header or include a field to your payload such as AJAX=1. Then you can check for those server side and take whatever action you think should be made for an AJAX request.
如果想要知道请求是否是AJAX有一些方便的原因,一些javascript库(如jQuery)会为您可以查找的AJAX请求添加额外的HTTP标头,或者您可以手动添加标头或在您的有效负载中包含一个字段等如AJAX = 1。然后,您可以检查那些服务器端,并采取您认为应该为AJAX请求执行的任何操作。
Of course there's nothing stopping me using CURL to make the same request with the right headers set to make the server think it's an AJAX request. You should therefore only use such tricks where whether or not the request was AJAX is of interest so you can format the response properly (send a HTML page if it's not AJAX, or JSON if it is). The security of your application can't rely on such tricks, and if the design of your application requires the ability to tell AJAX from non-AJAX for security or reliability reasons then you need to rethink the design of your application.
当然,没有什么能阻止我使用CURL来设置相同的请求,并使服务器认为它是一个AJAX请求。因此,您应该只使用这些技巧,无论请求是否是AJAX是有意义的,因此您可以正确格式化响应(如果不是AJAX则发送HTML页面,如果是,则发送JSON)。应用程序的安全性不能依赖于这些技巧,如果应用程序的设计需要能够出于安全性或可靠性的原因从非AJAX告诉AJAX,那么您需要重新考虑应用程序的设计。
In answer to what you're actually trying to achieve, there are a couple of approaches. None are completely reliable, though. The first approach is to deposit a cookie on the user's machine on first click, and to ignore any subsequent requests from that user agent if the cookie is in any subsequent requests. It's a fairly simple, lightweight approach, but it's also easily defeated by simply deleting the cookie, or refusing to accept it in the first place.
在回答您实际想要实现的目标时,有几种方法。但是,没有一个是完全可靠的。第一种方法是在第一次单击时在用户的计算机上存储cookie,如果cookie在任何后续请求中,则忽略来自该用户代理的任何后续请求。这是一种相当简单,轻量级的方法,但它也很容易通过简单地删除cookie或者首先拒绝接受它而被击败。
Alternatively, when the user makes the AJAX request, you can record some information about the requesting user agent along with the fact that a click was submitted. You can, for example store a hash (stored with something stronger than MD5!) of the client's IP and user agent string, along with a timestamp for the click. If you see a lot of the same hash, along with closely grouped timestamps, then there's possibly abuse being attempted. Again, this trick isn't 100% reliable because user agents can see any string they want as their user agent string.
或者,当用户发出AJAX请求时,您可以记录有关请求用户代理的一些信息以及提交点击的事实。例如,您可以存储客户端IP和用户代理字符串的哈希值(存储的内容比MD5强!),以及点击的时间戳。如果您看到许多相同的哈希值以及紧密分组的时间戳,那么可能会尝试滥用。同样,这个技巧不是100%可靠,因为用户代理可以看到他们想要的任何字符串作为其用户代理字符串。
#3
0
Use post method instead of get.Read the documentation here http://api.jquery.com/jQuery.post/ to learn how to use post method in jquery
使用post方法而不是get.Read文档http://api.jquery.com/jQuery.post/来学习如何在jquery中使用post方法
#4
0
You could, for example, implement a check if the request is really done with AJAX, and not by just calling the URL.
例如,您可以实现检查请求是否真的使用AJAX,而不是仅通过调用URL。
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// Yay, it is ajax!
} else {
// no AJAX, man..
}
#5
0
This solution may need more reflexion but might do the trick
这个解决方案可能需要更多的反思,但可能会有所帮助
You could use tokens as stated in Slicedpan's answer. When serving your page, you would generate uuids for each images and store them in session / database.
您可以使用Slicedpan的答案中所述的令牌。在为页面提供服务时,您将为每个图像生成uuids并将其存储在会话/数据库中。
Then serve your html as
然后将你的html服务为
<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>
Your ajax request would become
你的ajax请求会变成
$.ajax("action.php?action=click&uuid=uuidgenerated");
Then on php side, check for the uuid in your memory/database, and allow or not the transaction. (You can also check for custom headers sent on ajax as stated in other responses)
然后在php端,检查内存/数据库中的uuid,并允许或不允许该事务。 (您还可以检查ajax上发送的自定义标头,如其他响应中所述)
You would also need to purge uuids, on token lifetime, on window unload, on session expired...
你还需要在令牌生命周期,窗口卸载,会话过期时清除uuids ...
This method won't allow you to know if the request comes from an xhr but you'll be able to limit their number.
此方法不允许您知道请求是否来自xhr,但您可以限制其数量。