Использование учетных данных пользователя WordPress с помощью php-скрипта для отправки данных в приложение iOS

#php #ios #mysql #swift #wordpress

#php #iOS #mysql #swift #wordpress

Вопрос:

Итак, я последние два дня работал над *% amp; off, пытаясь заставить это работать, но я всегда застреваю на одной и той же части: сравнение пароля компьютера, полученного из приложения iOS, с хэшированным паролем, хранящимся в базе данных WordPress.

Небольшая справка: По сути, просто страница входа в систему на раскадровке ios, отправляющая электронное письмо и пароль, которые пользователь вводит в php-скрипт, который проверяет, совпадает ли хэшированный пароль, связанный с отправленным электронным письмом, с хэшированной версией отправленного пароля.

Swift и iOS здесь не проблема, поэтому я избавлю вас от этого кода. Я провожу тестирование с использованием PostMan для отправки HTTP-запроса POST с правильными параметрами :

  • Заголовок -> Тип содержимого: application/x-www-form-urlencoded
  • Тело —> электронная почта: email@email.com и пароль: testpasswd

Теперь вот исходный код для страницы входа :

 <?php

require("Connection.php");
require("SQLDao.php");
$email = htmlentities($_POST["email"]);
$password = htmlentities($_POST["password"]);
$returnValue = array();

echo json_encode("Hello World");

if(empty($email) || empty($password))
{
$returnValue["status"] = "error";
$returnValue["message"] = "There is a missing field";
echo json_encode($returnValue);
return;
}

$dao = new MySQLDao();
$dao->openConnection();
$userDetails = $dao->getUserDetailsWithPassword($email,$password);

if($userDetails) {
  $returnValue["status"] = "Success";
  $returnValue["message"] = "User logged in !";
  echo json_encode($returnValue);
} else {
  $returnValue["status"] = "error";
  $returnValue["message"] = "User not found";
  echo json_encode($returnValue);
}

$dao->closeConnection();

?>
  

Большинство из SQLDao.php в основном обрабатывает функции подключения SQL, но также и эту функцию :

 public function getUserDetailsWithPassword($email, $userPassword)
{
$returnValue = array();
$sql = "select id,user_email from vswp_users where user_email='" . $email . "' and user_pass='" .$userPassword . "'";

$result = $this->conn->query($sql);
  if ($result != null amp;amp; (mysqli_num_rows($result) >= 1)) {
    $row = $result->fetch_array(MYSQLI_ASSOC);
    if (!empty($row)) {
      $returnValue = $row;
    }
  }
  return $returnValue;
}
  

Но этот код, очевидно, проверяет отправленный пароль на хешированную версию WordPress, поэтому он всегда возвращает false .

Благодаря моим исследованиям я нашел это, но это не дало мне рабочего решения :

Исследование № 1: включить(phpass.php ) Функция CheckPassword, где у меня было бы что-то похожее на это :

 public function getUserDetailsWithHashedPassword($email, $userPassword)
{
  include_once("../wp-config.php");
  include_once("../wp-includes/class-phpass.php");
  $returnValue = array();
  $query = mysql_query("SELECT * FROM vswp_users WHERE user_email = '$email'");
  $row = mysql_fetch_array($query);

  $wp_hasher = new PasswordHash(8, TRUE);

  $password_hashed = $row['user_pass'];

  $passwordMatch = $wp_hasher->CheckPassword($userPassword, $password_hashed) || $password_hashed == md5($userPassword);

  if ($passwordMatch) {
    echo json_encode("Passwords match");
    $returnValue = TRUE;
  } else {
    echo json_encode("Passwords do not match");
    $returnValue = FALSE;
  }
  return $passwordMatch;
}
  

Но это просто возвращает «Hello World», но ни один из параметров if ($ passwordMatch) не отображается.

Прошу прощения за этот длинный вопрос, надеюсь, кто-нибудь сможет указать мне правильное направление, чтобы исправить это.

Спасибо за вашу помощь!!

РЕДАКТИРОВАТЬ 1: С помощью некоторого тестирования с использованием echo json_encode("Hello World"); я смог обнаружить, что в основном скрипт останавливается после строки —> УДАЛЕНО, ПОСКОЛЬКУ БОЛЬШЕ НЕ АКТУАЛЬНО

РЕДАКТИРОВАНИЕ 2: я приближаюсь, благодаря CBroe idea я смог найти больше информации с помощью надлежащей отчетности PHP. Я смог заставить это работать, поместив хэшированный пароль, хранящийся в базе данных, непосредственно в файл входа в систему в качестве значения $storedPassword , и это сработало. Но теперь единственная проблема, с которой я сталкиваюсь, заключается в том, что при выполнении этого с mysql я получаю следующую ошибку: substr() expects parameter 1 to be a string, array given in /[...]/class-phpass.php . Похоже, мне не хватает только кое-чего, чтобы преобразовать пароль из базы данных mysql в его строковую версию. Вот моя функция :

 public function getUserDetailsWithHashedPassword($email, $userPassword)
{
  require_once("/home/[hosting provider directories]/public_html/wp-includes/class-phpass.php");
  $returnValue = array();

  $sql = "select user_pass from vswp_users where user_email='" . $email . "'";
  $result = $this->conn->query($sql);
  if ($result != null amp;amp; (mysqli_num_rows($result) >= 1)) {
    $row = $result->fetch_array(MYSQLI_ASSOC);
    if (!empty($row)) {
      $storedPassword = $row;
    }
  }
  $wp_hasher = new PasswordHash(8, TRUE);
  $passwordMatch = $wp_hasher->CheckPassword($userPassword, $storedPassword);

  if($passwordMatch === TRUE) {
    $returnValue = TRUE;
  } else {
    $returnValue = FALSE;
  }
  return $returnValue;
}
  

Еще раз спасибо!!

Комментарии:

1. Включите правильное сообщение об ошибках PHP и проверьте ответ на сетевой панели браузера.

2. Хорошая идея. Я обнаружил, что действительно была проблема с require_once() URL-адресами.

3. Но теперь я получаю другую ошибку: «Класс ‘WP_User’ не найден в /[…]/pluggable.php . Есть идеи о том, что может быть причиной этого?

Ответ №1:

Сначала извлеките данные пользователя из базы данных. А затем проверьте хэшированный пароль пользователя с помощью обычного текстового пароля.

Чтобы получить пользователя, вы можете попробовать:

 $user = get_user_by( 'email', $email );
  

Затем:

 if ( $user amp;amp; wp_check_password( $userPassword, $user->data->user_pass, $user->ID) ){
    echo json_encode("Passwords match");
    $returnValue = TRUE;
}
else{
    echo json_encode("Passwords do not match");
    $returnValue = FALSE;
}
  

ссылки по теме:

wp_check_password

get_user_by

Комментарии:

1. И я предполагаю, что мне нужно было бы также поместить include_once("../wp-includes/pluggables.php"); ?

2. Я пробовал это, но, похоже, я все еще не получаю возвращаемое значение. «Hello Word» все еще отображается, но $returnValue в основном равно нулю.

3. Вам также необходимо включить wp-includes/pluggable.php для вызова get_user_by(..) . Пожалуйста, var_dump($user) и проверьте, что он возвращает. Также проверьте, какое значение имеет wp_check_password( $userPassword, $user->data->user_pass, $user->ID) .

Ответ №2:

Я, наконец, смог заставить это работать. Моя последняя проблема с $row заключалась в том, что я не указал, какой ключ массива я хотел отобразить. Вот рабочий код, если кто-нибудь окажется здесь и ему понадобится рабочее решение! (Очевидно, что [каталоги хостинг-провайдера] — это просто моя внутренняя файловая система, измените ее на свою, если потребуется)

 public function getUserDetailsWithHashedPassword($email, $userPassword)
{
  require_once("/home/[hosting provider directories]/public_html/wp-includes/class-phpass.php");
  $returnValue = array();

  $sql = "select user_pass from vswp_users where user_email='" . $email . "'";
  $result = $this->conn->query($sql);
  if ($result != null amp;amp; (mysqli_num_rows($result) >= 1)) {
    $row = $result->fetch_array(MYSQLI_ASSOC);
    if (!empty($row)) {
      $storedPassword = $row['user_pass'];
    }
  }
  $wp_hasher = new PasswordHash(8, TRUE);
  $passwordMatch = $wp_hasher->CheckPassword($userPassword, $storedPassword);

  if($passwordMatch === TRUE) {
    $returnValue = TRUE;
  } else {
    $returnValue = FALSE;
  }
  return $returnValue;
}
  

Ответ №3:

Я знаю, что это старый вопрос, но я хотел бы немного улучшить его, потому что он все еще работает сегодня, в 2021 году, и потому что class-phpass.php файл WordPress с тех пор также не сильно изменился.

Идея заключается в том, чтобы безопасно сопоставлять учетные данные WordPress, чтобы позволить пользователям входить во внешнюю программу, которая может либо находиться на том же сервере, либо нет (поскольку удаленная система имеет доступ к базе данных WordPress). Для удаленных систем потребуется копия class-phpass.php файла, в противном случае его можно просто запросить из его исходного местоположения в пути WordPress. Оба случая будут работать просто отлично.

Внесенные мной изменения минимальны, но значительны. Самое главное, я использую PDO вместо MySQLi.

Я также изменил функцию, позволяющую определять, предпринимается ли попытка входа с помощью имени пользователя или электронной почты. Это очень небольшое изменение, но оно очень помогает и может быть легко применено к тому или иному по мере необходимости.

Здесь новая функция:

 /** Request WordPress portable PHP password hashing framework */
require_once "/[PATH-TO-WORDPRESS]/wp-includes/class-phpass.php";

/**
 * Validate Login using WordPress user's information
 * 
 * @param  string  $login     The user login information (can either be username or email).
 * @param  string  $password  The unhashed password for the proposed account.
 * @return boolean            Returns TRUE if login/password combination is valid, FALSE otherwise.
 */
function validateLogin(string $login, string $password): bool
{
  global $pdo;

  /** Identify if $login is an email or a username */
  $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? "user_email" : "user_login";

  /** Request data from MySQL using PDO */
  $request = $pdo->prepare("SELECT user_pass FROM users WHERE {$field} = :login LIMIT 1");
  $request->bindValue(":login", $login, PDO::PARAM_STR);
  $request->execute();
  $result = $request->fetchAll();

  /** If $result is empty, simply fail the validation */
  if (empty($result)) return false;

  /**
   * Process the received $password against the hashed password from the user identified as $login
   * in the WordPress database and return the result of the validation process.
   */
  $wordpress_hasher = new PasswordHash(8, TRUE);
  return $wordpress_hasher->CheckPassword($password, $result[0]['user_pass']);
}
  

Конечно, я ожидаю, что вы будете знать, как установить подключение PDO вне функции и перед ее вызовом (в этом примере оно определено в глобальной переменной $pdo ). Если вы мало знаете о PDO, вот отличное руководство:https://phpdelusions.net/pdo_examples/connect_to_mysql

Я также включил class-phpass.php файл вне функции. Это * можно* включить в него, как это было сделано в исходном ответе, но я предпочел бы сделать иначе. 🙂

Если по какой-то причине вы предпочитаете, чтобы функция была менее совместима с PHP 7 или PHP 8, просто используйте ее следующим образом:

 function validateLogin($login, $password) 
{  
  [...]
}