如何解决密码提交时使用 AJAX 保护帖子内容并避免页面刷新
这是针对 WordPress 的,只是为了说明这一点。我在这里问是因为我怀疑我需要为这个问题提供赏金(价值 400)。
我需要在表单提交中添加 AJAX 以避免页面重新加载/页面刷新。我尝试了几个不同的版本,但没有一个有效。
这里的总体思路是保护帖子的一部分,该部分代码包含在 <pre>
和 <code>
标签中。
这些标签来自 prismjs
荧光笔,如下所示:
<pre><code class="language-php">code here</code></pre>
这些标签有四个不同的类;
- PHP
- HTML
- CSS
- JS
这就是 preg_replace
使用 ('/(<pre[^>]*>\s*<code[^>]*>)
格式的原因,因为它需要覆盖(处理)添加的类。
此外,还设置了 cookie,以便一旦用户提供了正确的密码,密码就会被记住。用户不必在每次查看包含受保护内容的帖子时都重新输入密码。
我有一个空的 DIV 作为显示消息(成功和错误)的占位符。这里的想法是在用户提交错误密码时显示错误。如果密码匹配,则显示内容(代码)。
这是我正在处理的代码:
add_filter( 'the_content','wrap_code_in_shortcode',9 );
function wrap_code_in_shortcode( $content ) {
if ( ! in_category( 'premium' ) ) return $content;
$content = preg_replace('/(<pre[^>]*>\s*<code[^>]*>)/',"[protected]$1",$content);
$content = preg_replace('/(<\/code>\s*<\/pre>)/',"$1[/protected]",$content);
return $content;
}
add_shortcode( 'protected','protected_function' );
function protected_function($atts,$content=null){
$userpass = isset( $_REQUEST['password']) ? $_REQUEST['password'] : (isset($_COOKIE['userpass']) ? $_COOKIE['userpass'] : NULL );
if ( in_array( $userpass,array('testpw') ) ) {
$return_code = do_shortcode( $content );
} else {
$return_code = '<div style="margin-top:20px; font-size:15px">Submit password to view.</div>
<div id="errorPWdata"></div>
<form method="post" onsubmit="protectedFunction(this);">
<input required style="display: block; width: 69%; height: 50px; margin-right: 1%; float: left; border: 2px solid #333;" type="text" placeholder=" Password Here" name="password" id="userpass">
<input style="display: block; margin: 0px; width: 30%; height: 50px; background-color: #333; color: #fff;" id="protectedButton" type="submit" value="Submit">
</form>';
?>
<script>
function protectedFunction(form) {
$('#protectedButton').on( 'click',function(e) {
e.preventDefault();
$.ajax({
success: function(data) {
$("#errorPWdata").html(data);
},error: function() {
alert("Password record error. Contact the administrator.");
}
});
document.cookie = "userpass=" + escape(form.userpass.value) + "; path=/";
}
}
</script>
<?php
}
return $return_code;
}
解决方法
我学会了详细说明您的代码片段并注意错误。 请先阅读所有内容,然后您可以尝试。
错误 1
Shortcode 定义了错误的函数名
add_shortcode( 'protected','shortcode_protected' );
应该换成
add_shortcode( 'protected','bio_protected_function' );
错误 2
脚本标签应该由入队系统替换以保证脚本序列。
代码片段
<script>
function protectedFunction(form) {
$('#protectedButton').on('click',function (e) {
e.preventDefault();
$.ajax({
success: function (data) {
$("#errorPWdata").html(data);
},error: function () {
alert("Password record error. Contact the administrator.");
}
});
document.cookie = "userpass=" + escape(form.userpass.value) + "; path=/";
}
}
</script>
应该换成这个
add_action( 'wp_enqueue_scripts',function () {
wp_enqueue_script(
'bio-shortcode-protected',get_theme_file_uri( 'assets/js/bio-shortcode-protected.js' ),[ 'jquery' ],'1',true
);
} );
wp_enqueue_scripts();
应创建适当的 bio-shortcode-protected.js 文件 path-to-your-theme/assets/js/bio-shortcode-protected.js(下一个错误的文件内容)
错误 3
-
默认情况下,WordPress 将 jQuery 作为全局 JavaScript 对象加载
jQuery
应该有效,而$
可能不会。脚本应以jQuery
包装器开头,以保证$
别名正常工作。 -
提供的脚本语法不正确。应该有一个关闭 父母符号
)
-
最好使用提交处理程序而不是点击处理程序。我通过处理
submit
而不是click
简化了您的处理程序。点击输入按钮触发submit
和click
处理程序不需要。
最后,bio-shortcode-protected.js 内容应该是
jQuery(function($){
const settings = window.bioShortcodeData;
function init() {
$('#protectedForm').on( 'submit',function(e) {
e.preventDefault();
const form = this;
$.post({
url: settings['endpoint'],data: {
'action': settings['action'],'bio-post-id': settings['post-id'],'nonce': settings['nonce'],'password': form.userpass.value,},success: function(data) {
if (!data.status) {
alert(data.message);
$('#errorPWdata')
.empty()
.append(data.message);
return;
}
if (data.isValidPassword) {
document.cookie = "userpass=" + escape(form.userpass.value) + "; path=/";
}
$('#bio-protected-content').replaceWith(data.content);
init() // for reattach submission handler
},error: function() {
alert("Server error");
}
});
})
}
init();
})
适当的一点点改进的短代码模板应该如下所示:
function bio_protected_function( $atts,$content = null ) {
add_action( 'wp_enqueue_scripts',function () {
wp_enqueue_script(
'bio-shortcode-protected',true
);
wp_localize_script(
'bio-shortcode-protected','bioShortcodeData',[
'post-id' => get_the_ID(),'nonce' => wp_create_nonce( 'bio-shortcode' ),'endpoint' => admin_url( 'admin-ajax.php' ),'action' => 'bio_protected_code'
]
);
} );
wp_enqueue_scripts();
if ( bio_validate_the_password() ) {
return do_shortcode( $content );
}
ob_start();
?>
<div class="bio-protected-content" id="bio-protected-content">
<div style="margin-top:20px; font-size:15px">Submit password to view.</div>
<div id="errorPWdata"></div>
<form method="post" id="protectedForm">
<input required
style="display: block; width: 69%; height: 50px; margin-right: 1%; float: left; border: 2px solid #333;"
type="text" placeholder=" Password Here" name="password" id="userpass">
<input style="display: block; margin: 0px; width: 30%; height: 50px; background-color: #333; color: #fff;"
id="protectedButton" type="submit" value="Submit">
</form>
</div>
<?php
return ob_get_clean();
}
错误 4
如果表单将被提交,将会发生什么 - WordPress 开始构建页面的内容,首先是页眉,内容(the_content 过滤器),然后是页脚。并检查短代码中的密码不是一个好主意。这样发送不必要的页面块。 AJAX 唯一需要获取的是干净的适当帖子内容。
这就是 ajax-endpoint 发挥作用的地方。端点应通过将代码片段放置到 functions.php 文件中来创建:
add_action( 'wp_ajax_nopriv_bio_protected_code','bio_protected_code_endpoint' );
add_action( 'wp_ajax_bio_protected_code','bio_protected_code_endpoint' );
function bio_protected_code_endpoint() {
$is_valid_nonce = wp_verify_nonce( $_REQUEST['nonce'],'bio-shortcode' );
if ( ! $is_valid_nonce ) {
wp_send_json(
[
'status' => false,'message' => 'Invalid nonce',]
);
exit;
}
$post_id = $_REQUEST['bio-post-id'];
$post_type = get_post_type( $post_id );
$available_post_type = 'your-post-type';
if ( $available_post_type !== $post_type ) {
wp_send_json(
[
'status' => false,'message' => 'Not available post type',]
);
exit;
}
global $post;
$post = get_post( $post_id );
$content = apply_filters( 'the_content',$post->post_content );
wp_send_json(
[
'status' => true,'isValidPassword' => bio_validate_the_password(),'content' => $content
]
);
exit;
}
和密码验证功能
function bio_validate_the_password() {
$userpass = $_REQUEST['password'] ?? $_COOKIE['userpass'] ?? null;
return in_array( $userpass,[ 'testpw' ] );
}
最后的话:
我不建议在 Cookie 中设置密码。这是潜在的安全漏洞。 最好设置会话密码变量。但这种方式也好不到哪里去。
有一个很好的答案,为什么不在会话中存储密码以及该怎么做。 Is it secure to store a password in a session?
,请尝试使用以下代码。
短代码处理部分:
// add [protected] shortcode to content.
add_filter( 'the_content','wrap_code_in_shortcode',9 );
function wrap_code_in_shortcode( $content ) {
if ( ! in_category( 'premium' ) ) return $content;
$content = preg_replace('/(<pre[^>]*>\s*<code[^>]*>)/',"[protected]$1",$content);
$content = preg_replace('/(<\/code>\s*<\/pre>)/',"$1[/protected]",$content);
return $content;
}
// function to check if password is valid
function is_user_password_valid($userpass,$post_id) {
return in_array( $userpass,array('test') );
}
// define shortcode. you can combine(merge) this section with wrap_code_in_shortcode()
add_shortcode( 'protected','shortcode_protected' );
function shortcode_protected($atts,$content=null){
$userpass = isset( $_REQUEST['password']) ? $_REQUEST['password'] : (isset($_COOKIE['userpass']) ? $_COOKIE['userpass'] : NULL );
$post_id = get_the_ID();
if ( is_user_password_valid($userpass,$post_id) ) {
$return_code = do_shortcode( $content );
} else {
$return_code =
'<div id="protected-area">
<div style="margin-top:20px; font-size:15px">Submit password to view.</div>
<form method="post" onsubmit="getProtectedContent(event);">
<input required type="text" placeholder=" Password Here" name="password">
<input type="submit" value="Submit">
</form>
</div><!-- end of #protected-area -->';
$return_code .= '<script>
function getProtectedContent(event) {
event.preventDefault();
let password = event.target.elements.password.value;
jQuery.ajax({
url: "' . admin_url('admin-ajax.php') . '",method: "POST",data: {
action: "get_protected_content",post_id: ' . $post_id . ',password
},success: function(result) {
if (result.success) {
jQuery("#protected-area").html(result.data);
document.cookie = "userpass=" + password + "; path=/";
} else {
alert(result.data);
}
},error: function() {
alert("Something is wrong.");
}
});
return false;
}
</script>';
}
return $return_code;
}
Ajax 请求处理部分:
add_action( 'wp_ajax_get_protected_content','get_protected_content' );
add_action( 'wp_ajax_nopriv_get_protected_content','get_protected_content' );
function get_protected_content() {
// validation
if ( empty( $_POST['post_id'] ) ) {
wp_send_json_error( 'Wrong Post ID' );
}
$post_id = (int)$_POST['post_id'];
if ( empty( $_POST['password'] ) || ! is_user_password_valid( $_POST['password'],$post_id ) ) {
wp_send_json_error( 'Wrong Password' );
}
$content = get_post_field( 'post_content',$post_id );
// var_dump($content);
if ( preg_match( '/(<pre[^>]*>\s*<code[^>]*>.*<\/code>\s*<\/pre>)/',$content,$matches ) ) {
wp_send_json_success( apply_filters( 'the_content',$matches[1] ) );
} else {
wp_send_json_error( 'No Protected Content Found' );
}
}
希望此代码对您有所帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。