Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm trying to create an admin option page without the Settings API for some reasons. Then if I do so, I've heard that I need to use nonces for security. I'd like to know the correct way to use them.

This is what I've tried by following this page: Using nonce external of WP Admin admin.

<?php
/*
Plugin Name: Demo for Using Nonce
Description: Demo plugin demonstrating how to use nonce
Author: Teno
*/

// define constants
define("DEMONONCE", "demo_nonce");
define("DEMONONCEPAGESLUG", "demo_nonce_adminpage");

// create an option array
$arrOption = get_option(DEMONONCE);
update_option(DEMONONCE, array_merge(array(), is_array($arrOption) ? $arrOption : array()));

// admin menu
add_action('admin_menu', 'demo_nonce_adminmenu');
function demo_nonce_adminmenu() {
    add_options_page('Demo Plugin Menu for Nonce without Settings API', 'Demo Plugin Menu for Nonce without Settings API', 'manage_options', DEMONONCEPAGESLUG, 'demo_nonce_adminpage');
}
// admin page
function demo_nonce_adminpage() {
    $options = get_option(DEMONONCE);

    print_r($_POST); // for debugging
    echo '<br />';

    if(isset($_POST[DEMONONCE]['submitted']) && !wp_verify_nonce($_POST['name_of_nonce_field'], 'name_of_my_action')){
        return;
    }

    if(isset($_POST[DEMONONCE]['submitted']) && $_POST[DEMONONCE]['submitted'] == 1){
        if (strlen(trim($_POST[DEMONONCE]['option_a'])) == 0) {
            $options['invalid'] = True;     
            echo '<div class="error settings-error"><p>Options are not saved.</p></div>';
        } else {    
            $options = array_merge($options, $_POST[DEMONONCE]); // it seems the tab caption is erased here
            update_option(DEMONONCE, $options);
            echo '<div class="updated"><p>Updates are saved.</p></div>';
        }
    }   
    ?>
    <div class="wrap">
        <?php // heading 
        screen_icon(); ?> <h2>Demo Plugin for Nonces without Settings API</h2>
        <h3>Page 1</h3>
        <form method="post" action="">  <?php // 'action=""' means to send the form post data to this page itself. ?>
            <?php wp_nonce_field('name_of_my_action', 'name_of_nonce_field'); ?>
            <input type="hidden" name="<?php echo DEMONONCE; ?>[submitted]" value="1" />
            <table class="form-table">
                <tbody>
                <tr valign="top">
                    <th scope="row">Option A</th>
                    <td>
                        <input name="<?php echo DEMONONCE; ?>[option_a]" size="40" type="text" value="<?php echo $options['invalid']  ? $_POST[DEMONONCE]['option_a'] : $options['option_a']; ?>" />
                        <?php echo ($options['invalid'] && $options['invalid'] ) ? '<font color="red">* cannot be blank.</font>' :'' ?>
                    </td>
                </tr>
                <tr valign="top">
                    <th scope="row">Option B</th>
                    <td>
                        <input name="<?php echo DEMONONCE; ?>[option_b]" size="40" type="text" value="<?php echo $options['invalid'] ? $_POST[DEMONONCE]['option_b'] : $options['option_b']; ?>" />
                    </td>
                </tr>
                </tbody>
            </table>
            <?php submit_button(); ?>   
        </form>     
    </div> <!-- end the admin page wrapper -->
    <?php
}
?>

I placed if(isset($_POST[DEMONONCE]['submitted']) && !wp_verify_nonce($_POST['name_of_nonce_field'], 'name_of_my_action')){ return; } before displaying the form and placed <?php wp_nonce_field('name_of_my_action', 'name_of_nonce_field'); ?> in the form tag.

I'm still not sure if this is all okey. What strings should I put for 'name_of_nonce_field' and 'name_of_my_action' ? Could they be whatever I name?

And what else should I do besides nonces for creating a more secure administration page?

share|improve this question
    
You would get a better answer if your code was a bit more focussed, but I will give it a try. –  Jake Aug 23 '12 at 2:13

1 Answer 1

up vote 1 down vote accepted

This is a very basic nonce setup for a plugin:

Create your nonce input in the form:

wp_nonce_field( basename(__FILE__), $nonce_key );

Then check your nonce once submitted:

if ( empty($_POST[$nonce_key]) || ! wp_verify_nonce( $_POST[$nonce_key], basename(__FILE__) ) ) return;

basename(FILE) just uses the current filename (eg: plugin_options.php) to create the nonce string. You need to provide a string that the nonce function will use to create a number unique to your task. The string you use to create the nonce number needs to be the same string you use check it.

You could create a custom string as well, for example: "demononce9384374", as long as you can use it to create the nonce and then check it later. It can remain constant in your plugin, it doesn't ever need to change. The nonce uses other variables to change the nonce string such as user id and time.

So in my example, "basename(FILE)" is my string, and will remain constant unless I am setting and checking in two different files, then it would cause a problem.

So your example should work great.

I think you are pretty covered. Outlining the correct capabilities (manage_options) in your "add_options_page" function and correctly checking the nonce should be good.

Edit: Escaping

It just occurred to me that I left a topic of security: Escaping

When you are outputting information to the page that has been submitted by a user, even on the backend.

These two functions are what I use most: esc_attr() & esc_html()

You can also add translation with esc_attr__() or esc_attr_e() & esc_html__() or esc_html_e()

For example:

value="<?php echo $options['invalid']  ? esc_attr($_POST[DEMONONCE]['option_a']) : esc_attr($options['option_a']); ?>"

More here: http://markjaquith.wordpress.com/2009/06/12/escaping-api-updates-for-wordpress-2-8/

share|improve this answer
    
Could it be whatever assigned to the string value for the variable $nonce_key? –  Teno Aug 23 '12 at 2:51
    
Yeah. Usually something associated with your plugin/theme, but anything you want really. Just so it is the same on creation and testing. –  Jake Aug 23 '12 at 15:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.