我想禁用"当前密码";字段,当用户尝试更改密码时。用户经常在密码上遇到困难,当忘记密码时,无法询问当前密码。
用户编辑表单如下:https://woocommerce.github.io/code-reference/files/woocommerce-templates-myaccount-form-edit-account.html
我尝试删除与第50行到53行相关的内容,这将是当前密码字段,但这还不够,当前密码仍然需要。
然后我想围绕所需属性工作,但它不存在于表单中,显然wordpress以另一种方式要求验证。
如何解决这个问题?
模板名称: form-edit-account.php
<?php
/**
* Edit account form
*
* This template can be overridden by copying it to yourtheme/woocommerce/myaccount/form-edit-account.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://docs.woocommerce.com/document/template-structure/
* @package WooCommerceTemplates
* @version 3.5.0
*/
defined( 'ABSPATH' ) || exit;
do_action( 'woocommerce_before_edit_account_form' ); ?>
<form class="woocommerce-EditAccountForm edit-account" action="" method="post" <?php do_action( 'woocommerce_edit_account_form_tag' ); ?> >
<?php do_action( 'woocommerce_edit_account_form_start' ); ?>
<p class="woocommerce-form-row woocommerce-form-row--first form-row form-row-first">
<label for="account_first_name"><?php esc_html_e( 'First name', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_first_name" id="account_first_name" autocomplete="given-name" value="<?php echo esc_attr( $user->first_name ); ?>" />
</p>
<p class="woocommerce-form-row woocommerce-form-row--last form-row form-row-last">
<label for="account_last_name"><?php esc_html_e( 'Last name', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_last_name" id="account_last_name" autocomplete="family-name" value="<?php echo esc_attr( $user->last_name ); ?>" />
</p>
<div class="clear"></div>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="account_display_name"><?php esc_html_e( 'Display name', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_display_name" id="account_display_name" value="<?php echo esc_attr( $user->display_name ); ?>" /> <span><em><?php esc_html_e( 'This will be how your name will be displayed in the account section and in reviews', 'woocommerce' ); ?></em></span>
</p>
<div class="clear"></div>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="account_email"><?php esc_html_e( 'Email address', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="email" class="woocommerce-Input woocommerce-Input--email input-text" name="account_email" id="account_email" autocomplete="email" value="<?php echo esc_attr( $user->user_email ); ?>" />
</p>
<fieldset>
<legend><?php esc_html_e( 'Password change', 'woocommerce' ); ?></legend>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_current"><?php esc_html_e( 'Current password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_current" id="password_current" autocomplete="off" />
</p>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_1"><?php esc_html_e( 'New password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_1" id="password_1" autocomplete="off" />
</p>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_2"><?php esc_html_e( 'Confirm new password', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_2" id="password_2" autocomplete="off" />
</p>
</fieldset>
<div class="clear"></div>
<?php do_action( 'woocommerce_edit_account_form' ); ?>
<p>
<?php wp_nonce_field( 'save_account_details', 'save-account-details-nonce' ); ?>
<button type="submit" class="woocommerce-Button button" name="save_account_details" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>"><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
<input type="hidden" name="action" value="save_account_details" />
</p>
<?php do_action( 'woocommerce_edit_account_form_end' ); ?>
</form>
<?php do_action( 'woocommerce_after_edit_account_form' ); ?>
注意:如上所述,最好不要做任何更改,因为这会降低应用程序的安全性。然而,为了回答你的问题:
虽然可以通过覆盖模板文件轻松修改当前密码字段的输出,但验证是硬编码的可以在/includes/class-wc-form-handler.php文件中找到。
要绕过验证,我们必须传递2个错误消息,即:
- 请输入当前密码
- 您当前的密码不正确
绕过,我们不打算使用实际的当前密码,但我们将创建/添加额外的自定义数据,并在此基础上允许用户更改他的密码。
1)要绕过第一个通知,你必须覆盖/myaccount/form-edit-account.php模板文件。
替换第50 - 53行@version 3.5.0
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_current"><?php esc_html_e( 'Current password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_current" id="password_current" autocomplete="off" />
</p>
<?php
// Get userID
$user_id = $user->ID;
// Generate salt
$salt = md5( openssl_random_pseudo_bytes( 32, $cstrong ) . wp_generate_password( 32, true, true ) );
$enc = $user_id . '::' . crypt( $user_id, $salt );
// NOT empty
if ( ! empty ( $enc ) ) {
update_user_meta( $user_id, '_enc', $enc );
}
// Encodes data with MIME base64
$value = base64_encode( $enc );
// NOT empty
if ( ! empty ( $value ) ) {
?>
<input type="hidden" name="password_current" id="password_current" value="<?php echo $value; ?>" />
<?php
} else {
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_current"><?php esc_html_e( 'Current password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_current" id="password_current" autocomplete="off" />
</p>
<?php
}
?>
这将用指定值的隐藏输入字段替换当前密码字段。该值基于当前的userID
和一个盐,当请求页面时,它被保存为user_meta
。
2)要绕过第二个通知,你可以使用check_password() WordPress过滤器钩子
/**
* Filters whether the plaintext password matches the encrypted password.
*
* @since 2.5.0
*
* @param bool $check Whether the passwords match.
* @param string $password The plaintext password.
* @param string $hash The hashed password.
* @param string|int $user_id User ID. Can be empty.
*/
function filter_check_password( $check, $password, $hash, $user_id ) {
// Only for WooCommerce edit-account endpoint
if ( ! is_wc_endpoint_url( 'edit-account' ) ) return $check;
// Get meta
$enc = get_user_meta( $user_id, '_enc', true );
// NOT empty
if ( ! empty ( $enc ) ) {
// Get parts
$parts = explode( '::', base64_decode( $password ) );
// Compare user ID and data
if ( $parts[0] == $user_id && str_contains( $enc, $parts[1] ) ) {
$check = true;
}
}
return $check;
}
add_filter( 'check_password', 'filter_check_password', 10, 4 );
这将确保使用我们的自定义user_meta
而不是使用真实的当前密码(加密)。当匹配时,我们允许修改密码