218 lines
6.4 KiB
PHP
218 lines
6.4 KiB
PHP
<?php
|
|
/**
|
|
* AKSRT Theme Auth Router
|
|
*
|
|
* 统一处理主题内认证路由:
|
|
* - /login
|
|
* - /register
|
|
* - /bind-account
|
|
* - /reset-password
|
|
* - /logout
|
|
* - wp-login.php 前台分流
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
final class AKSRT_Auth_Router {
|
|
|
|
private static $instance = null;
|
|
|
|
public static function get_instance(): self {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
private function __construct() {}
|
|
|
|
public function init(): void {
|
|
add_filter('query_vars', [$this, 'register_query_vars']);
|
|
add_action('init', [$this, 'register_rewrite_rules']);
|
|
add_filter('template_include', [$this, 'handle_template_include'], 99);
|
|
add_action('init', [$this, 'maybe_flush_rewrite_rules']);
|
|
|
|
add_filter('login_url', [$this, 'filter_login_url'], 10, 3);
|
|
add_filter('lostpassword_url', [$this, 'filter_lostpassword_url'], 10, 2);
|
|
add_filter('register_url', [$this, 'filter_register_url']);
|
|
add_filter('logout_url', [$this, 'filter_logout_url'], 10, 2);
|
|
|
|
add_action('login_init', [$this, 'redirect_native_login']);
|
|
add_action('template_redirect', [$this, 'handle_logout_route']);
|
|
}
|
|
|
|
public function register_query_vars(array $vars): array {
|
|
$vars[] = 'aksrt_sign';
|
|
$vars[] = 'aksrt_auth_tab';
|
|
$vars[] = 'aksrt_logout';
|
|
return $vars;
|
|
}
|
|
|
|
private function auth_route_map(): array {
|
|
return [
|
|
'login' => 'index.php?aksrt_sign=1&aksrt_auth_tab=login',
|
|
'register' => 'index.php?aksrt_sign=1&aksrt_auth_tab=register',
|
|
'bind-account' => 'index.php?aksrt_sign=1&aksrt_auth_tab=bind',
|
|
'logout' => 'index.php?aksrt_logout=1',
|
|
'reset-password' => 'index.php?aksrt_sign=1&aksrt_auth_tab=reset-password',
|
|
'verify-email' => 'index.php?aksrt_sign=1&aksrt_auth_tab=verify-email',
|
|
];
|
|
}
|
|
|
|
public function register_rewrite_rules(): void {
|
|
foreach ($this->auth_route_map() as $path => $query) {
|
|
add_rewrite_rule('^' . preg_quote($path, '/') . '/?$', $query, 'top');
|
|
}
|
|
}
|
|
|
|
public function handle_template_include(string $template): string {
|
|
if (get_query_var('aksrt_sign')) {
|
|
// §4.1 Global sign gate: when close_sign is active, block non-logged-in access to sign page
|
|
if (class_exists('AKSRT_Settings') && AKSRT_Settings::close_sign() && !is_user_logged_in()) {
|
|
$tab = (string) get_query_var('aksrt_auth_tab');
|
|
if (!in_array($tab, ['reset-password', 'verify-email', 'bind-account'], true) && empty($_REQUEST['interim-login'])) {
|
|
if (!headers_sent()) {
|
|
wp_safe_redirect(home_url('/'), 302);
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
$auth_template = function_exists('aksrt_get_auth_template_file')
|
|
? aksrt_get_auth_template_file((string) get_query_var('aksrt_auth_tab'), true)
|
|
: 'templates/pages/page-sign.php';
|
|
$tpl = aksrt_locate_template_file($auth_template);
|
|
if ($tpl) {
|
|
return $tpl;
|
|
}
|
|
}
|
|
|
|
return $template;
|
|
}
|
|
|
|
public function maybe_flush_rewrite_rules(): void {
|
|
$rewrite_version = AKSRT_VERSION . ':sign-router-v1';
|
|
if (get_option('aksrt_auth_routes_flushed') !== $rewrite_version) {
|
|
flush_rewrite_rules(false);
|
|
update_option('aksrt_auth_routes_flushed', $rewrite_version);
|
|
}
|
|
}
|
|
|
|
public function filter_login_url(string $login_url, string $redirect, bool $force_reauth): string {
|
|
if (strpos($login_url, 'wp-login.php') === false) {
|
|
return $login_url;
|
|
}
|
|
|
|
$custom_login_url = aksrt_get_login_url();
|
|
if ($redirect !== '') {
|
|
$custom_login_url = add_query_arg('redirect_to', urlencode($redirect), $custom_login_url);
|
|
}
|
|
if ($force_reauth) {
|
|
$custom_login_url = add_query_arg('reauth', '1', $custom_login_url);
|
|
}
|
|
|
|
return $custom_login_url;
|
|
}
|
|
|
|
public function filter_lostpassword_url(string $lostpassword_url, string $redirect): string {
|
|
$custom_url = aksrt_get_reset_password_url();
|
|
if ($redirect !== '') {
|
|
$custom_url = add_query_arg('redirect_to', urlencode($redirect), $custom_url);
|
|
}
|
|
return $custom_url;
|
|
}
|
|
|
|
public function filter_register_url(string $register_url): string {
|
|
return aksrt_get_register_url();
|
|
}
|
|
|
|
public function filter_logout_url(string $logout_url, string $redirect): string {
|
|
return aksrt_get_logout_url($redirect ?: home_url('/'));
|
|
}
|
|
|
|
public function redirect_native_login(): void {
|
|
if (wp_doing_ajax()) {
|
|
return;
|
|
}
|
|
|
|
// §4.1 Emergency bypass key (admin_sign_key): allow wp-login.php direct access when key matches
|
|
if (isset($_GET['aksrt_bypass'])) {
|
|
$key = class_exists('AKSRT_Settings') ? AKSRT_Settings::admin_sign_key() : '';
|
|
if ($key !== '' && hash_equals($key, (string) $_GET['aksrt_bypass'])) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
$action = isset($_REQUEST['action']) ? sanitize_key((string) $_REQUEST['action']) : 'login';
|
|
$redirect_to = isset($_REQUEST['redirect_to']) ? wp_unslash((string) $_REQUEST['redirect_to']) : '';
|
|
$interim = !empty($_REQUEST['interim-login']);
|
|
$reauth = !empty($_REQUEST['reauth']);
|
|
$is_admin_target = $redirect_to !== '' && strpos($redirect_to, admin_url()) === 0;
|
|
|
|
if (is_user_logged_in() && current_user_can('manage_options')) {
|
|
return;
|
|
}
|
|
|
|
if ($is_admin_target || $interim || $reauth || $action === 'logout') {
|
|
return;
|
|
}
|
|
|
|
switch ($action) {
|
|
case 'register':
|
|
$target = aksrt_get_register_url();
|
|
break;
|
|
case 'lostpassword':
|
|
$target = aksrt_get_reset_password_url();
|
|
break;
|
|
case 'rp':
|
|
case 'resetpass':
|
|
$target = add_query_arg('legacy', '1', aksrt_get_reset_password_url());
|
|
break;
|
|
default:
|
|
$target = aksrt_get_login_url();
|
|
break;
|
|
}
|
|
|
|
$passthrough = [];
|
|
if ($redirect_to !== '') {
|
|
$passthrough['redirect_to'] = $redirect_to;
|
|
}
|
|
if ($reauth) {
|
|
$passthrough['reauth'] = '1';
|
|
}
|
|
if (!empty($_REQUEST['obk'])) {
|
|
$passthrough['obk'] = sanitize_text_field((string) $_REQUEST['obk']);
|
|
}
|
|
|
|
if (!empty($passthrough)) {
|
|
$target = add_query_arg($passthrough, $target);
|
|
}
|
|
|
|
wp_safe_redirect($target, 302);
|
|
exit;
|
|
}
|
|
|
|
public function handle_logout_route(): void {
|
|
if (!get_query_var('aksrt_logout')) {
|
|
return;
|
|
}
|
|
|
|
if (!is_user_logged_in()) {
|
|
wp_safe_redirect(home_url('/'));
|
|
exit;
|
|
}
|
|
|
|
$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field((string) $_GET['_wpnonce']) : '';
|
|
if (!wp_verify_nonce($nonce, 'aksrt-logout')) {
|
|
wp_die(__('退出登录请求无效,请重试。', 'aksrt'));
|
|
}
|
|
|
|
$redirect_to = isset($_GET['redirect_to']) ? wp_unslash((string) $_GET['redirect_to']) : home_url('/');
|
|
wp_logout();
|
|
wp_safe_redirect($redirect_to ?: home_url('/'));
|
|
exit;
|
|
}
|
|
}
|