I am aware of nonces to check for intentions but can’t make any sense if I can use them to restrict for database reads somehow? I mean, I am fetching records from the database using AJAX but I don’t want anyone to have that data by some other means (POST requests to that admin-ajax.php
page).
For example, in my AJAX handler I have this much of work (I am sending $myid
along with the action in the AJAX call):
$myid = 5575;
$query = "SELECT `id` FROM table WHERE `user_id` = $myid;";
$data = $wpdb->get_col( $query );
echo json_encode($data);
die();
I am calling this much of data through AJAX, how can I protect it from evil users who can try to make direct POST calls to that page?
Edit: @Bainternet Thanks for the detailed explanation, appreciate that but my question is really about what @Milo said and I can see that unless I can create a unique nonce for that request, I can’t do anything as per @goldenapples. Right?
I am handling all this stuff with Facebook JS SDK, so everything that has to be done is with AJAX only (without page load), and whatever I can think of making the user sign in wp_signon()
or anything, anyone else can do that too without authority. So, I don’t have any uniqueness in a user who is actually using the site and the one who is trying to get read some data out other than the site makes the call to fetch the data. And whatever I can do to make it login or anything, that can be replicated by someone else too. Can anyone think of something?
Update: I think I have found a workaround by just calling it with action
and get other parameters from Facebook using PHP SDK. But I am still open for suggestions or anything else for that matter.
There are a few things you can do to make more secure:
First the Ajax call it self should be made with a WordPress nonce like you said:
In the above code mind the two attributes
action
and_ajax_nonce
which both are needed to verify the call to admin-ajax.php, in the first few lines of code it check if an action was sent to the server and if not then itdie()
‘s (FIRST CHECK) then using that action you with an action hook you call your own ajax function:and if you want both logged in users and none logged in visitors to access this function the use both hooks (SECOND CHECK).
then in you ajax function the first thing you should do is check for the ajax referrer (THIRD CHECK):
next when running queries on database with user input you should use
$wpdb->prepare
for escaping and validation so instead of:use:
I am not entirely sure how secure this is, but WordPress Ajax handlers are user-aware (I guess request is still request so cookies are checked and if user is logged in that is accounted for). So you can make usual
current_user_can()
check in them.presumably one is logged in when making this request? you can hash some data and create a unique per-user nonce on your page, pass it with your ajax request, and check it against the logged in user. or maybe I’m misunderstanding what you’re doing here.