api de gestion de ticket, basé sur php-crud-api. Le but est de décorrélé les outils de gestion des données, afin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BasicAuthMiddleware.php 3.2KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. <?php
  2. namespace Tqdev\PhpCrudApi\Middleware;
  3. use Tqdev\PhpCrudApi\Controller\Responder;
  4. use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
  5. use Tqdev\PhpCrudApi\Record\ErrorCode;
  6. use Tqdev\PhpCrudApi\Request;
  7. use Tqdev\PhpCrudApi\Response;
  8. class BasicAuthMiddleware extends Middleware
  9. {
  10. private function isAllowed(String $username, String $password, array &$passwords): bool
  11. {
  12. $hash = isset($passwords[$username]) ? $passwords[$username] : false;
  13. if ($hash && password_verify($password, $hash)) {
  14. if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
  15. $passwords[$username] = password_hash($password, PASSWORD_DEFAULT);
  16. }
  17. return true;
  18. }
  19. return false;
  20. }
  21. private function authenticate(String $username, String $password, String $passwordFile): bool
  22. {
  23. if (session_status() == PHP_SESSION_NONE) {
  24. session_start();
  25. }
  26. if (isset($_SESSION['user']) && $_SESSION['user'] == $username) {
  27. return true;
  28. }
  29. $passwords = $this->readPasswords($passwordFile);
  30. $allowed = $this->isAllowed($username, $password, $passwords);
  31. if ($allowed) {
  32. $_SESSION['user'] = $username;
  33. }
  34. $this->writePasswords($passwordFile, $passwords);
  35. return $allowed;
  36. }
  37. private function readPasswords(String $passwordFile): array
  38. {
  39. $passwords = [];
  40. $passwordLines = file($passwordFile);
  41. foreach ($passwordLines as $passwordLine) {
  42. if (strpos($passwordLine, ':') !== false) {
  43. list($username, $hash) = explode(':', trim($passwordLine), 2);
  44. if (strlen($hash) > 0 && $hash[0] != '$') {
  45. $hash = password_hash($hash, PASSWORD_DEFAULT);
  46. }
  47. $passwords[$username] = $hash;
  48. }
  49. }
  50. return $passwords;
  51. }
  52. private function writePasswords(String $passwordFile, array $passwords): bool
  53. {
  54. $success = false;
  55. $passwordFileContents = '';
  56. foreach ($passwords as $username => $hash) {
  57. $passwordFileContents .= "$username:$hash\n";
  58. }
  59. if (file_get_contents($passwordFile) != $passwordFileContents) {
  60. $success = file_put_contents($passwordFile, $passwordFileContents) !== false;
  61. }
  62. return $success;
  63. }
  64. public function handle(Request $request): Response
  65. {
  66. $username = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
  67. $password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
  68. $passwordFile = $this->getProperty('passwordFile', '.htpasswd');
  69. if (!$username) {
  70. $response = $this->responder->error(ErrorCode::AUTHORIZATION_REQUIRED, $username);
  71. $realm = $this->getProperty('realm', 'Username and password required');
  72. $response->addHeader('WWW-Authenticate', "Basic realm=\"$realm\"");
  73. } elseif (!$this->authenticate($username, $password, $passwordFile)) {
  74. $response = $this->responder->error(ErrorCode::ACCESS_DENIED, $username);
  75. } else {
  76. $response = $this->next->handle($request);
  77. }
  78. return $response;
  79. }
  80. }