Users.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the Sonata Project package.
  5. *
  6. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. class Users
  12. {
  13. public function __construct(string $file = '../users.dat')
  14. {
  15. $this->userFile = $file;
  16. $this->users = json_decode(file_get_contents($file), true);
  17. }
  18. public function hasSession()
  19. {
  20. session_start();
  21. if (isset($_SESSION['username'])) {
  22. return $_SESSION['username'];
  23. }
  24. return false;
  25. }
  26. public function storeData(User $user): void
  27. {
  28. $this->users[$user->getUsername()] = $user->getData();
  29. file_put_contents($this->userFile, json_encode($this->users));
  30. }
  31. public function loadUser($name)
  32. {
  33. if (isset($this->users[$name])) {
  34. return new User($name, $this->users[$name]);
  35. }
  36. return false;
  37. }
  38. }
  39. class User
  40. {
  41. public function __construct($user, $data)
  42. {
  43. $this->data = $data;
  44. $this->user = $user;
  45. }
  46. public function auth($pass)
  47. {
  48. if ($this->data['password'] === $pass) {
  49. return true;
  50. }
  51. return false;
  52. }
  53. public function startSession(): void
  54. {
  55. $_SESSION['username'] = $this->user;
  56. }
  57. public function doLogin(): void
  58. {
  59. session_regenerate_id();
  60. $_SESSION['loggedin'] = true;
  61. $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];
  62. }
  63. public function doOTP(): void
  64. {
  65. $_SESSION['OTP'] = true;
  66. }
  67. public function isOTP()
  68. {
  69. if (isset($_SESSION['OTP']) && true == $_SESSION['OTP']) {
  70. return true;
  71. }
  72. return false;
  73. }
  74. public function isLoggedIn()
  75. {
  76. if (isset($_SESSION['loggedin']) && true == $_SESSION['loggedin'] &&
  77. isset($_SESSION['ua']) && $_SESSION['ua'] == $_SERVER['HTTP_USER_AGENT']
  78. ) {
  79. return $_SESSION['username'];
  80. }
  81. return false;
  82. }
  83. public function getUsername()
  84. {
  85. return $this->user;
  86. }
  87. public function getSecret()
  88. {
  89. if (isset($this->data['secret'])) {
  90. return $this->data['secret'];
  91. }
  92. return false;
  93. }
  94. public function generateSecret()
  95. {
  96. $g = new \Sonata\GoogleAuthenticator\GoogleAuthenticator();
  97. $secret = $g->generateSecret();
  98. $this->data['secret'] = $secret;
  99. return $secret;
  100. }
  101. public function getData()
  102. {
  103. return $this->data;
  104. }
  105. public function setOTPCookie(): void
  106. {
  107. $time = floor(time() / (3600 * 24)); // get day number
  108. //about using the user agent: It's easy to fake it, but it increases the barrier for stealing and reusing cookies nevertheless
  109. // and it doesn't do any harm (except that it's invalid after a browser upgrade, but that may be even intented)
  110. $cookie = $time.':'.hash_hmac('sha1', $this->getUsername().':'.$time.':'.$_SERVER['HTTP_USER_AGENT'], $this->getSecret());
  111. setcookie('otp', $cookie, time() + (30 * 24 * 3600), null, null, null, true);
  112. }
  113. public function hasValidOTPCookie()
  114. {
  115. // 0 = tomorrow it is invalid
  116. $daysUntilInvalid = 0;
  117. $time = (string) floor((time() / (3600 * 24))); // get day number
  118. if (isset($_COOKIE['otp'])) {
  119. list($otpday, $hash) = explode(':', $_COOKIE['otp']);
  120. if ($otpday >= $time - $daysUntilInvalid && $hash == hash_hmac('sha1', $this->getUsername().':'.$otpday.':'.$_SERVER['HTTP_USER_AGENT'], $this->getSecret())) {
  121. return true;
  122. }
  123. }
  124. return false;
  125. }
  126. }