WordPress Plugin Development
WordPress Plugin Development In Bangla Part-9: WordPress Plugins Security with Nonce
WordPress এ Nonce কি?
WordPress এ Nonce (number used once) হচ্ছে মূলতঃ WordPress এ randomly generated security hash সিস্টেম, tokens বা একটা unique identifiers , যা দিয়ে আমরা form ,url অথবা ajax request কোথায় থেকে আসছে , তা চেক করতে পারি। এবং এর মাধ্যমে WordPress site এ যেকোনো ক্ষতিকর attack থেকে সুরক্ষা দিতে পারি।
WordPress এ Nonce security প্রধানের জন্য ফাঙ্কশন গুলো দুইভাগে বিভক্ত :
1. Creating a Nonce
- wp_nonce_url() – সাইটে যেকোনো URL তৈরির সময় তার সাথে একটা nonce যুক্ত করার কাজে ব্যবহৃত হয়। এবং URL এ অবস্থিত & গুলোকে & তে escapes করে।
- wp_nonce_field() – সাইটের মধ্যে যেকোনো form এ একটা nonce hidden field যুক্ত করার কাজে ব্যবহৃত হয়।
- wp_create_nonce() – custom nonce তৈরির কাজে ব্যবহৃত হয়। বিশেষ করে ajax request এর সময় এটি বেশি ব্যবহৃত হয়।এছাড়া আপনি চাইলে এটাকে form, url এমনকি session এর জন্য ও ব্যবহার করতে পারেন।
2. Verifying a Nonce
- check_admin_referer() –শুধু মাত্র এক admin screen থেকে অন্য admin screen এর জন্য pass হওয়া nonce কে ভেরিফাই করার কাজে ব্যবহৃত হয়।
- check_ajax_referer() – ajax এর জন্য nonce চেক করে। অর্থাৎ ajax request টি যদি আপন সাইট থেকে আসে, তাহলে সাইটে একসেস এর সুযোগ দিবে। অন্যথায় script execution সাথে সাথে terminate করে দিবে।
- wp_verify_nonce() – Time limit দিয়ে nonce চেক করার জন্য এটি ব্যবহৃত হয়।
wp_nonce_url() Function Syntax
wp_nonce_url( string $actionurl, int|string $action = -1, string $name = '_wpnonce' )
Parameters#
- $actionurl (string) (Required) যেই URL এ nonce action টি যুক্ত করবেন , তা এখানে দিতে হবে।
- $action (int|string) (Optional) Nonce এর action টির নাম এখানে দিতে পারেন। Default value: -1
- $name (string) (Optional) Nonce এর একটা নাম দিতে পারেন। Default value: ‘_wpnonce’
উদাহরণঃ
// Sample URL, note the & in there $url = 'http://localhost/?arg1=value1&arg2=value2'; // This will show http://localhost/?arg1=value1&arg2=value2&_wpnonce=abcdef echo wp_nonce_url( $url, 'action' ); // This will return http://localhost/?arg1=value1&arg2=value2&_wpnonce=abcdef echo add_query_arg( '_wpnonce', wp_create_nonce( 'action' ), $url );
wp_verify_nonce() function syntax
wp_verify_nonce( string $nonce, string|int $action = -1 );
Parameters #
- $nonce (string) (Required) যেই Nonce value কে verification করবেন, তা এখানে হবে, এটা সাধারণত form, url অথবা ajax রিকোয়েস্ট থেকে এসে থাকে।
$action (string|int) (Optional) nonce টি যেই স্ট্রিং বা টোকেনের বিপরীতে তৈরি করেছিলেন , তা এখানে হবে। Default value: -1
URL Nonce Verification Plugin
এখন আমরা URL দিয়ে আসা একটা nonce কে ভেরিফিকেশন কিভাবে করা যায়, তা একটা প্লাগিনের মাধ্যমে দেখব। নিচের প্লাগিন টি দেখুন :
<?php /* Plugin Name: W3 URL Nonce Checking Plugin Plugin URI: https://github.com/w3programmers/w3-url-nonce/ Description: W3 URL Nonce Checking Plugin Author: Masud Alam Version: 1.0.0 Author URI: https://blog.w3programmers.com/ */ add_action('admin_menu', 'add_my_plugin_admin_screen'); function add_my_plugin_admin_screen () { add_options_page( __('My Plugin Settings', 'my-plugin-textdomain'), __('My Plugin', 'my-plugin-textdomain'), 'manage_options', 'my_plugin_settings', 'my_plugin_do_something' ); } function my_plugin_do_something () { if (!isset($_GET['my_nonce']) || !wp_verify_nonce($_GET['my_nonce'], 'doing_something')) { ?> <h2><?php esc_html_e('My Plugin Admin Screen', 'my-plugin-textdomain');?></h2> <p> <a href="<?php print wp_nonce_url(admin_url('options-general.php?page=my_plugin_settings'), 'doing_something', 'my_nonce');?>" class="button button-primary"><?php esc_html_e('Do Something!', 'my-plugin-textdomain');?></a> <span class="description"><?php esc_html_e('This button does something interesting.', 'my-plugin-textdomain');?></span> </p> <?php } else { // User pressed "Do Something!" button, so // do something interesting. $nonce=$_GET['my_nonce']; echo "Hey! Your Nonce is: ".$nonce,"<br>"; $nonce = wp_verify_nonce( $nonce, 'doing_something' ); switch ( $nonce ) { case 1: echo 'Nonce is less than 12 hours old'; break; case 2: echo 'Nonce is between 12 and 24 hours old'; break; default: exit( 'Nonce is invalid' ); } } }
এখন যদি, আপনি প্লাগিনটি activate করেন, তাহলে নিচের মতো আপনার nonce রেজাল্ট দেখতে পাবেন।
এখন যদি, আপনি বাটনটি ক্লিক করেন , তাহলে নিচের মতো nonce value দেখতে পাবেন।
wp_nonce_field() function syntax
wp_nonce_field( int|string $action = -1, string $name = '_wpnonce', bool $referer = true, bool $echo = true )
Parameters #
- $action (int|string) (Optional) চাইলে এখানে একটা Action এর নাম দিতে পারেন। Default value: -1
- $name (string) (Optional) এখানে Nonce এর নামটি দিতে পারেন। Default value: ‘_wpnonce’
- $referer (bool) (Optional) referer field টি validation করবে কিনা তার জন্য এখানে একটা বুলিয়ান ভ্যালু দিতে পারেন। Default value: true
- $echo (bool) (Optional) hidden form field টি display নাকি return করবে , তা এখানে বলতে পারেন। Default value: true
উদাহরণঃ
<form method="post"> <!-- some inputs here ... --> <?php wp_nonce_field( 'name_of_my_action', 'name_of_nonce_field' ); ?> </form>
Form Nonce Verification Plugin
এখন আমরা wp_nonce_field() function এবং form ব্যবহার করে একটা প্লাগিন তৈরি করে ফেলব। চলুন শুরু করা যাক।
<?php /* Plugin Name: W3 Form Nonce Checking Plugin Plugin URI: https://github.com/w3programmers/w3-nonce-form/ Description: W3 Form Nonce Checking Plugin Author: Masud Alam Version: 1.0.0 Author URI: https://blog.w3programmers.com/ */ add_action('admin_menu', 'add_w3_nonce_form_admin_screen'); function add_w3_nonce_form_admin_screen () { add_options_page( __('W3 Nonce Form Plugin Settings', 'w3-nonce-form-plugin-textdomain'), __('W3 Nonce Form Plugin', 'w3-nonce-form-plugin-textdomain'), 'manage_options', 'w3_nonce_form_plugin_settings', 'w3_nonce_form_plugin_do_something' ); } function w3_nonce_form_plugin_do_something () { if (!isset($_REQUEST['w3_nonce_field']) || !wp_verify_nonce($_REQUEST['w3_nonce_field'], 'doing_something')) { ?> <h2><?php esc_html_e('W3 Nonce Form Plugin Admin Screen', 'w3-nonce-form-plugin-textdomain');?></h2> <form method="post" action="<?php echo admin_url('options-general.php?page=w3_nonce_form_plugin_settings');?>"> <!-- some inputs here ... --> <?php wp_nonce_field( 'doing_something', 'w3_nonce_field' ); ?> <input class="button button-primary" type="submit" value="Check Nonce Value" name="submit"> </form> <?php } else { // User pressed "Do Something!" button, so // do something interesting. $nonce=$_REQUEST['w3_nonce_field']; echo "Hey! Your Nonce is: ".$nonce,"<br>"; $nonce = wp_verify_nonce( $nonce, 'doing_something' ); switch ( $nonce ) { case 1: echo 'Nonce is less than 12 hours old'; break; case 2: echo 'Nonce is between 12 and 24 hours old'; break; default: exit( 'Nonce is invalid' ); } } }
এখন যদি আপনি form টি সাবমিট করেন , তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন।
wp_create_nonce() Function Syntax
wp_create_nonce( string|int $action = -1 )
Parameter #
- $action (int|string) (Optional) চাইলে এখানে একটা Action এর নাম দিতে পারেন। Default value: -1
উদাহরণঃ
/* * Step A: Create an nonce for a link. * We pass it as a GET parameter. * The target page will perform some action based on the 'do_something' parameter. */ $nonce = wp_create_nonce( 'my-nonce' ); ?> <a href='myplugin.php?do_something=some_action&_wpnonce=<?php echo esc_attr( $nonce ); ?>'><?php esc_html_e( 'Do some action', 'textdomain' ); ?></a> /* * Step B: This code would go in the target page. * We need to verify the nonce. */ $nonce = $_REQUEST['_wpnonce']; if ( ! wp_verify_nonce( $nonce, 'my-nonce' ) ) { // This nonce is not valid. die( __( 'Security check', 'textdomain' ) ); } else { // The nonce was valid. // Do stuff here. }
তবে specific কিছু চেক করার জন্য ও আমরা চাইলে wp_create_nonce() function টি ব্যবহার করতে পারি। যেমন আপনি একটা ডিলিট রিকোয়েস্ট নিচের মতো করে nonce সহ পাঠাতে পারেন।
wp_create_nonce( 'delete_post-' . $post_id );
আর ডিলিট করার সময় , নিচের মতো করে ভেরিফাই করে নিতে পারবেন।
wp_verify_nonce( $nonce, "delete_post-{$_REQUEST['post_id']}" );
AJAX Request Nonce Verification Plugin
এখন আমরা wp_create_nonce() function এবং ajax ব্যবহার করে একটা প্লাগিন তৈরি করে ফেলব। চলুন শুরু করা যাক।
<?php /* Plugin Name: W3 Demo Ajax Plugin Description: An Example of AJAX in WordPress Plugin Plugin URI: https://github.com/w3programmers/w3-demo-ajax Version: 1.0.0 Author: Masud Alam Author URI: https://blog.w3programmers.com Text Domain: w3-demo-ajax */ add_action( 'admin_enqueue_scripts', 'my_enqueue' ); function my_enqueue() { wp_register_script( 'ajax-script', plugins_url( '/js/script.js', __FILE__ ), array('jquery') ); wp_enqueue_script('ajax-script'); // in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.name $ajax_nonce = wp_create_nonce( "w3-security" ); wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => $ajax_nonce, 'name' => "Masud Alam", 'age'=>35, )); } add_action("wp_ajax_{$_REQUEST['action']}", 'receive_data' ); function receive_data() { $nonce = $_POST['nonce']; if (!wp_verify_nonce( $nonce, 'w3-security' ) ){ die ( 'Busted!'); } $name= $_POST['name']; $age= $_POST['age']; echo "Welcome! ".$name." You're ".$age." Years Old! Your Uniquue Security Code: $nonce"; wp_die(); // this is required to terminate immediately and return a proper response }
এবার আপনার plugin ফোল্ডারের মধ্যে , js/script.js ফাইলে নিচের কোডগুলো লিখুন।
jQuery(document).ready(function($) { var data = { 'action': 'send_data', 'name': ajax_object.name, // We pass php values differently! 'age' :ajax_object.age, 'nonce':ajax_object.nonce, }; // We can also pass the url value separately from ajaxurl for front end AJAX implementations jQuery.post(ajax_object.ajax_url, data, function(response) { alert(response); }); });
এখন যদি আপনি প্লাগিনটি activate করেন, তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন:
check_ajax_referer() Function Syntax
check_ajax_referer( int|string $action = -1, false|string $query_arg = false, bool $die = true )
Parameters #
- $action (int|string) (Optional) চাইলে এখানে action nonce অর্থাৎ যেই string এর nonce তৈরী করেছেন , তা এখানে দিতে পারেন। Default value: -1
- $query_arg (false|string) (Optional) $_REQUEST দিয়ে যেই নামে receive করবেন, চাইলে সেটি এখানে দিতে পারেন। যদি false থাকে তাহেল বাই ডিফল্ট এখানে ভ্যালু হিসেবে নিবে ‘_ajax_nonce’, এবং ‘_wpnonce’ . Default value: false
- $die (bool) (Optional) AJAX nonce না মিললে সাথে সাথে script execution অফ হবে কিনা , তা এখানে চাইলে দিতে পারেন Default value: true
উদাহরণঃ
এখন চাইলে আপনি আমাদের উপরের “W3 Demo Ajax Plugin” এ wp_verify_nonce() ফাঙ্কশনটি ব্যবহারের পরিবর্তে check_ajax_referer() ফাঙ্কশনটি ব্যবহার করতে পারেন। নিচে লক্ষ্য করুন :
<?php /* Plugin Name: W3 Demo Ajax Plugin Description: An Example of AJAX in WordPress Plugin Plugin URI: https://github.com/w3programmers/w3-demo-ajax Version: 1.0.0 Author: Masud Alam Author URI: https://blog.w3programmers.com Text Domain: w3-demo-ajax */ add_action( 'admin_enqueue_scripts', 'my_enqueue' ); function my_enqueue() { wp_register_script( 'ajax-script', plugins_url( '/js/script.js', __FILE__ ), array('jquery') ); wp_enqueue_script('ajax-script'); // in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.name $ajax_nonce = wp_create_nonce( "w3-security" ); wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => $ajax_nonce, 'name' => "Masud Alam", 'age'=>35, )); } add_action("wp_ajax_{$_REQUEST['action']}", 'receive_data' ); function receive_data() { $nonce = $_POST['nonce']; /* if (!wp_verify_nonce( $nonce, 'w3-security' ) ){ die ( 'Busted!'); } */ check_ajax_referer( 'w3-security', 'nonce', true ); $name= $_POST['name']; $age= $_POST['age']; echo "Welcome! ".$name." You're ".$age." Years Old! Your Uniquue Security Code: $nonce"; wp_die(); // this is required to terminate immediately and return a proper response }
check_admin_referer() Function Syntax
check_admin_referer( int|string $action = -1, string $query_arg = '_wpnonce' );
Parameters #
- $action (int|string) (Optional) nonce action টির নাম এখানে হবে। Default value: -1
- $query_arg (string) (Optional) nonce field এর নামটি এখানে হবে। অর্থাৎ যেই key দিয়ে আপনি $_REQUEST দিয়ে nonce value রিসিভ করবেন। Default value: ‘_wpnonce’
উদাহরণঃ
এখন আমরা আমাদের ইতিমধ্যে ডেভেলপ করা “W3 Form Nonce Checking Plugin” এ wp_verify_nonce() ফাঙ্কশনের পরিবর্তে check_admin_referer() function দিয়ে নতুন করে সাজাবো। নিম্নে লক্ষ্য করুন :
<?php /* Plugin Name: W3 Form Nonce Checking Plugin Plugin URI: https://github.com/w3programmers/w3-nonce-form/ Description: W3 Form Nonce Checking Plugin Author: Masud Alam Version: 1.0.0 Author URI: https://blog.w3programmers.com/ */ add_action('admin_menu', 'add_w3_nonce_form_admin_screen'); function add_w3_nonce_form_admin_screen () { add_options_page( __('W3 Nonce Form Plugin Settings', 'w3-nonce-form-plugin-textdomain'), __('W3 Nonce Form Plugin', 'w3-nonce-form-plugin-textdomain'), 'manage_options', 'w3_nonce_form_plugin_settings', 'w3_nonce_form_plugin_do_something' ); } function w3_nonce_form_plugin_do_something () { ?> <h2><?php esc_html_e('W3 Nonce Form Plugin Admin Screen', 'w3-nonce-form-plugin-textdomain');?></h2> <?php if ( ! empty( $_POST ) && check_admin_referer( 'doing_something', 'w3_nonce_field' ) ){ // User pressed "Do Something!" button, so // do something interesting. $nonce=$_REQUEST['w3_nonce_field']; echo "Hey! Your Nonce is: ".$nonce,"<br>"; } ?> <form method="post" action="<?php echo admin_url('options-general.php?page=w3_nonce_form_plugin_settings');?>"> <!-- some inputs here ... --> <?php wp_nonce_field( 'doing_something', 'w3_nonce_field' ); ?> <input class="button button-primary" type="submit" value="Check Nonce Value" name="submit"> </form> <?php }
এখন যদি আপনি Plugin টি Activate করেন , তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন।
আর যদি আপনি form টি submit করেন , তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন।
আবার যদি nonce ঠিক না থাকে , তাহলে check_admin_referer() function ইমিডিয়েট নিচের মতো রেজাল্ট দিবে।