Upon successful login wp_signon()
sets a cookie in the http response header. Hence it has to be called before any HTML output is sent to the browser. Otherwise the “headers already sent” error will occur.
After a successfull login you should redirect your user. Otherwise the login information will not present when the page HTML is rendered.
A very sketchy but working code:
// process login requests each time wordpress renders a page.
function my_custom_login_process() {
// check if login credentials are present in the current http request
if ( isset( $_POST['user_login'] ) && isset( $_POST['user_password'] ) ) {
// try login
$user = wp_signon( $_POST );
if ( is_wp_error($user) ) // didn't work. Tell the user.
exit('Nope...');
else // worked! Get him somewhere.
wp_redirect( get_bloginfo('url') );
}
}
add_action('after_setup_theme','my_custom_login_process');
Additionally you should protect your login form with a nonce, and add a nonce verification to the function above. The easiest way to do this is by using wp_nonce_field()
in the login form.
Nonces explained
[EDIT]: A Nonce is a unique token, that gets registered along with a form. It is mainly used to make sure that a form has been generated by the Webserver, before any data is accepted for further processing. All forms in the admin area are using nonces (or at least should do).
During the login process it will provide basic protection against brute force attacks. (This means flooding your WordPress with blank POST requests containing arbitrary username / password combinations.)
(BTW: It seems like you have a little misconception on hooks. You really should not register (do_action()
) and call a hook (do_action()
) with arbitrary function arguments. Other plugins might also have registered their functions. This article looks like a pretty good starting point for a deeper understanding.)