How does check_ajax_referer() really work? - ajax

Smart Wordpress people say that plugin developers should employ a nonce in each AJAX request that is sent from a page back to the wordpress blog (admin-ajax.php).
This is done by (1) generating a nonce on the server side, via
$nonce = wp_create_nonce ('my-nonce');
...(2) making that nonce available to Javascript code that sends AJAX requests. For example you could do it like this:
function myplg_emit_scriptblock() {
$nonce = wp_create_nonce('myplg-nonce');
echo "<script type='text/javascript'>\n" .
" var WpPlgSettings = {\n" .
" ajaxurl : '" . admin_url( 'admin-ajax.php' ) . "',\n" .
" nonce : '" . $nonce . "'\n" .
" };\n" .
"</script>\n";
}
add_action('wp_print_scripts','myplg_emit_scriptblock');
...and then (3) the javascript ajax logic references that global variable.
var url = WpPlgSettings.ajaxurl +
"?action=my-wp-plg-action&" +
"nonce=" + WpPlgSettings .nonce +
"docid=" + id;
$.ajax({type: "GET",
url: url,
headers : { "Accept" : 'application/json' },
dataType: "json",
cache: false,
error: function (xhr, textStatus, errorThrown) {
...
},
success: function (data, textStatus, xhr) {
...
}
});
...and finally (4) checking the received nonce in the server-side logic.
add_action( 'wp_ajax_nopriv_skydrv-hotlink', 'myplg_handle_ajax_request' );
add_action( 'wp_ajax_skydrv-hotlink', 'myplg_handle_ajax_request' );
function myplg_handle_ajax_request() {
check_ajax_referer( 'myplg-nonce', 'nonce' ); // <<=-----
if (isset($_GET['docid'])) {
$docid = $_GET['docid'];
$response = myplg_generate_the_response($docid);
header( "Content-Type: application/json" );
echo json_encode( $response ) ;
}
else {
$response = array("error" => "you must specify a docid parameter.");
echo json_encode( $response ) ;
}
exit;
}
But how does the check really work?

Revising some AJAX procedures, I came to the same question. And it's a simple matter of checking the function code:
function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
if ( $query_arg )
$nonce = $_REQUEST[$query_arg];
else
$nonce = isset($_REQUEST['_ajax_nonce']) ? $_REQUEST['_ajax_nonce'] : $_REQUEST['_wpnonce'];
$result = wp_verify_nonce( $nonce, $action );
if ( $die && false == $result ) {
if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
wp_die( -1 );
else
die( '-1' );
}
do_action('check_ajax_referer', $action, $result);
return $result;
}
If wp_verify_nonce is false and you haven't sent false in the $die parameter, then it will execute wp_die( -1 );.
In your sample code, check_ajax_referer() will break the execution and return -1 to the AJAX call. If you want to handle the error yourself, add the parameter $die and do your stuff with $do_check:
$do_check = check_ajax_referer( 'myplg-nonce', 'nonce', false );
Note that the proper way to handle AJAX in WordPress is: register, enqueue and localize the JavaScript files using wp_enqueue_scripts instead of wp_print_scripts.
See Use wp_enqueue_scripts() not wp_print_styles().
Check this update in December 2020 from a core contributor h/t: Rafael Atías:
Apparently we should now use wp_add_inline_script instead of wp_localize_script to expose a global object that needs to be used by your script.

It is just a test that the "nonce" code matches what was given, so a hacker can't cut in and get a shortcut to your database. If the security code doesn't match, the php will die and the page will halt.
"If you code is correctly verified it will continue past, if not it will trigger die('-1'); stopping your code dead."

Related

Shortcode doesn't work on ajax call in Wordpress

I have big problem with loading ajax content in Wordpress. Ajax loading works but inside loaded file is shortcode which is show as plain text. I tried many many solutions that supposed to work but none of it works... My code is:
echo do_shortcode( apply_filters( 'the_content', $post->post_content ) );
But even if I hard code shortcode it still show as plain text. Actually I use Content no cache plugin but I tried different things and result is the same. I need to execute this shortcode. I need to use ajax to avoid cache. Any ideas?
This is my whole code for now:
add_action( 'wp_ajax_showBanner', 'showBanner' );
add_action( 'wp_ajax_nopriv_showBanner', 'showBanner' );
function showBanner() {
echo do_shortcode( '[adrotate group="1"]' );
wp_die();
}
function getBanner() {
echo '<div class="adr"></div>
<script>
window.addEventListener( "load", function() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "' . admin_url( 'admin-ajax.php' ) . '", true);
xhttp.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded;");
xhttp.onload = function () {
if (this.status >= 200 && this.status < 400) {
document.querySelector( ".adr" ).innerHTML = this.responseText;
} else {
document.querySelector( ".adr" ).innerHTML = "Error";
}
};
xhttp.send("action=showBanner");
});
</script>';
}

How to get update ACF fields from AJAX form data

I can send the data to admin-ajax.php and see that the data exists via my dev tools, however, I cannot seem to be able to take that data and update an ACF field, or perhaps my function to do that is not running.
Here is my PHP:
// define the actions for the two hooks created, first for logged in users and the next for logged out users
add_action( 'wp_ajax_add_dog_to_favorites', 'add_dog_to_favorites' );
add_action( 'wp_ajax_nopriv_add_dog_to_favorites', 'login_to_add_to_favorites' );
// define the function to be fired for logged in users
function add_dog_to_favorites() {
// nonce check for an extra layer of security, the function will exit if it fails
if (!wp_verify_nonce( $_REQUEST['nonce'], 'add_dog_to_favorites_nonce' )) {
exit('Woof Woof Woof');
}
// Get the post_id and user_id value from the form and update the ACF form "test_field".
$post_id = $_REQUEST["post_id"];
$userID = $_REQUEST('user_id');
$current_field = get_field('test_field', $userID);
update_field('test_field', $post_id, $userID);
if ($current_field === false) {
$result['type'] = 'error';
} else {
$result['type'] = 'success';
}
// Check if action was fired via Ajax call. If yes, JS code will be triggered, else the user is redirected to the post page
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$result = json_encode($result);
echo $result;
} else {
header("Location: " . $_SERVER['HTTP_REFERER']);
}
// don't forget to end your scripts with a die() function - very important
die();
}
// define the function to be fired for logged out users
function login_to_add_to_favorites() {
echo 'You must log in to like';
die();
}
// used here only for enabling syntax highlighting. Leave this out if it's already included in your plugin file.
// Fires after WordPress has finished loading, but before any headers are sent.
add_action( 'init', 'enqueue_add_dog_to_favorites_script' );
function enqueue_add_dog_to_favorites_script() {
// Register the JS file with a unique handle, file location, and an array of dependencies
wp_register_script( 'add_favorites_script', plugin_dir_url( __FILE__ ) . 'add_favorites_script.js', array('jquery') );
// localize the script to your domain name, so that you can reference the url to admin-ajax.php file easily
wp_localize_script( 'add_favorites_script', 'myAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
// enqueue jQuery library and the script you registered above
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'add_favorites_script' );
}
and my JS:
jQuery(document).ready( function() {
jQuery(".not-favorite").click( function(e) {
e.preventDefault();
post_id = jQuery(this).attr("data-post_id");
nonce = jQuery(this).attr("data-nonce");
user_id = jQuery(this).attr("data-user_id");
jQuery.ajax({
type : "post",
dataType : "json",
url : myAjax.ajaxurl,
data : {action: "add_dog_to_favorites", post_id : post_id, nonce: nonce, user_id : user_id},
success: function(response) {
if(response.type == "success") {
console.log('success!');
}
else {
alert("Your like could not be added");
}
}
});
});
});
I have a console.log('success!'); line that should trigger if successful, but it is not triggering. The failure alert is also not triggering, which leads me to believe the function is not running at all? I feel like it's pretty close to working, but just can't get there.
Any help would be greatly appreciated!
Update: Ok. I found that the function is actually exiting because of the nonce verification:
if (!wp_verify_nonce( $_REQUEST['nonce'], 'add_dog_to_favorites_nonce' )) {
exit('Woof Woof Woof');
}
I have tried commenting this block of code out to see what would happen and I get a critical error.
Update: Fixed an error in my code that allows it to work without the nonce check.
$userID = $_REQUEST('user_id'); needs to be $userID = $_REQUEST['user_id'];
I still will need to get the nonce check working, but progress is being made. If anyone knows why that is not working, that would wrap this up!

While sending post request using ajax it is showing error

I am using this code for sending ajax request but it is showing 400 Bad request error. anyone please tell me the error in this. i am totally stucked.
Thanks.
function bulk_setup_post_type()
{
wp_enqueue_style( 'customstyle', plugins_url( 'admin/css/custom.css' , __FILE__ ) );
wp_enqueue_script( 'customjs', plugins_url( 'admin/js/custom.js' , __FILE__ ) );
wp_localize_script('customjs', 'ajax_object', array('ajax_url' => admin_url('admin-ajax.php')));
}
add_action('wp_register_scripts', 'bulk_setup_post_type');
add_action('wp_ajax_extract_upload_data', 'extract_upload_data');
add_action('wp_ajax_nopriv_extract_upload_data', 'extract_upload_data');
function abc(file){
if(file!='')
{
jQuery.ajax({
url : ajax_object.ajax_url,
type : 'POST',
data : {
action : 'extract_upload_data',
path : file,
},
success : function( response ) {
//console.log(response);
alert(response);
}
});
}
else{ alert('File ' + file + 'not found.');}
}
I believe your URL contains no domain name

Get shortcode content via ajax failed on wordpress 4.9.8

For a custom needs, i should load content of some posts via ajax into a custom template page.
i used apply_filters( 'the_content', $key->content ); and it was working perfect on my wordpress pages. But when i have update the version of WP to 4.9.8
it has stopped and ajax response is just an empty string for some shortcodes or a non completely loaded content for some others.
after some search i add this snippet
/* --- Necessary since Visual Compoer V 4.9 --- */
if ( class_exists( 'WPBMap' )
&& method_exists( 'WPBMap',
'addAllMappedShortcodes' ) ) {
WPBMap::addAllMappedShortcodes();
}
else{
do_action( 'template_redirect' );
}
but the problem was not solved!
My code is:
jQuery.ajax({
url: postdigital.ajax_url,
type: 'post',
data: {
action: 'get_activContent_byID_posts',
post_id: idContent
},
success: function (response) {
// console.log(response+' tesssst');
}
});
add_action( 'wp_ajax_nopriv_get_activContent_byID_posts', 'get_activContent_byID_posts' );
add_action( 'wp_ajax_get_activContent_byID_posts', 'get_activContent_byID_posts' );
function get_activContent_byID_posts(){
global $wpdb;
$divContent=$wpdb->get_results("SELECT type, content FROM `tablename` WHERE id=".$_REQUEST['post_id']);
/* --- Necessary since Visual Compoer V 4.9 --- */
if ( class_exists( 'WPBMap' ) && method_exists( 'WPBMap', 'addAllMappedShortcodes' ) ) {
WPBMap::addAllMappedShortcodes();
}
else{
do_action( 'template_redirect' );
}
foreach($divContent as $key)
{
$html= apply_filters( 'the_content', $key->content );
}
echo $html;
wp_die(); // wp_die() instead of die() provides better integration with WordPress
}

Dynamically remove cart fees Woocommerce

I have a WordPress store using the Woocommerce plugin. I am currently able to add fees dynamically at checkout using the $woocommerce->cart->add_fee() function, assigned to the woocommerce_cart_calculate_fees hook. However, I would also like to be able to remove fees at checkout as well, but I haven't managed to make it work. I am attempting to trigger a PHP function via AJAX that will then clear the fees using this method.
When I simply echo 'success' from the clearfees() function, the AJAX call completes successfully. However, when I try calling $WC()->cart->remove_all_fees() AJAX fails with a 500 error.
Remove fees AJAX call from Javascript
function clear_fees() {
$.ajax({
type: 'GET',
url: entrada_params.admin_ajax_url,
data: { action : 'clear_fees' }
}).done( function( data ) {
console.log(data);
} )
.fail( function( jqXHR, textStatus, errorThrown ) { // HTTP Error
console.error( errorThrown );
} );
}
The clearfees function in my theme's functions.php
function clearfees() {
$WC()->cart->remove_all_fees();
wp_die();
}
// creating Ajax call for WordPress
add_action('wp_ajax_clear_fees', 'clearfees');
add_action('wp_ajax_nopriv_clear_fees', 'clearfees');
In my searching I've found very little information on the remove_all_fees() function in practice but it seems like the logical solution if I can get it to work.
i am doing this as i am apply fees in function.php
add_action( 'woocommerce_cart_calculate_fees', 'custom_fee_based_on_cart_total', 10, 1 );
function custom_fee_based_on_cart_total( $cart_object ) {
if(isset($_GET['implementation'])){
$charges = (int)$_GET['charges'];
$cart_total = (int)$cart_object->cart_contents_total;
$fees = $cart_total + $charges;
$applyfee = $_SESSION['applyfee'] ? $_SESSION['applyfee'] : 'true';
if($applyfee == 'true'){
$cart_object->add_fee( __( "Implementation Charges", "woocommerce" ), $charges, false );
}else{
$charges = 0;
$cart_object->add_fee( __( "Implementation Charges", "woocommerce" ), $charges, false );
}
}
}
and if i select remove fees option
function clearfees() {
$_SESSION['applyfee'] = 'false';
}
// creating Ajax call for WordPress
add_action('wp_ajax_clear_fees', 'clearfees');
add_action('wp_ajax_nopriv_clear_fees', 'clearfees');
and at last refresh cart page as i get success responce.

Resources