Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> samoistna zmiana użytkownika i błąd 1045
Hesto
post
Post #1





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


Witam,
Posiadam serwer w pewnej firmie hostingowej.
Mam problem ze skryptem php.
1. Łączę się z bazą danych - wszystko jest ok
2. wykonuje jakiekolwiek zapytanie do bazy danych np.: instrukcje SELECT - wszystko jest ok
3. następnie wykonuje jakiekolwiek inne zapytanie do bazy danych mysql i wyskakuje błąd:

Błąd MySQL #1045: Access denied for user 'XXX'@'localhost' (using password: NO)

Co ciekawe:
XXX - jest to pierwszy użytkownik, pierwszej bazy danych jaką stworzyłem na tym serwerze dawno temu. Do połączenia z bazą (w mysql_connect) NIE używam tego użytkownika tylko zupełnie innego YYY. Skrypt jakby sam przełącza na tego użytkownika po zakończeniu pierwszego zapytania. Kiedy zorientowałem się że samoistnie przełącza tego użytkownika pomyślałem że w takim razie będę używał XXX do łączenia się z bazą danych, to skrypt nie będzie musiał go przełączać - niestety, ten sam błąd.
Użytkownik XXX i YYY mają takie same uprawnienia. (wszystkie)

Bardzo proszę o pomoc.

Ten post edytował Hesto 14.11.2013, 14:16:10
Go to the top of the page
+Quote Post
freemp3
post
Post #2





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Sprawdź czy gdzieś w skrypcie nie jest ładowany plik, z tymi starymi danymi lub gdzieś jest błąd. Raczej wątpie, żeby skrypt sam się w taki sposób przełączał.
Druga sprawa to taka, że mimo iż hasła są identyczne przy drugiej próbuje połączenia nie jest ono podawane, o czym świadczy treść komunikatu:
Kod
(using password: NO)
Go to the top of the page
+Quote Post
Hesto
post
Post #3





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


  1. <?php
  2. class database {
  3.  
  4. public $query;
  5. public $result;
  6. public $records_rows;
  7. public $records;
  8. public $dbHost;
  9. public $dbUser;
  10. public $dbHaslo;
  11. public $dbName;
  12. public $connection;
  13.  
  14. public function __construct()
  15. {
  16. $this -> query = NULL;
  17. $this -> result = NULL;
  18. $this -> records_rows = NULL;
  19. $this -> records = array();
  20. $this -> dbHost = ''; // nazwa hosta
  21. $this -> dbUser = 'YYY'; // login do bazy
  22. $this -> dbHaslo = ''; // hasło do bazy
  23. $this -> dbName = ''; // nazwa bazy danych
  24. $this -> connection = FALSE;
  25. }
  26.  
  27. public function sqlError()
  28. {
  29.  
  30. echo '<br><b>Błąd MySQL #'.mysql_errno().'</b>: '.mysql_error() .'<br>';
  31. }
  32.  
  33. public function sqlConnect()
  34. {
  35. $this -> connection = (@mysql_connect($this -> dbHost, $this -> dbUser, $this -> dbHaslo) == TRUE);
  36.  
  37. if (($this -> connection == TRUE) && ($this -> dbName != ''))
  38. {
  39. if ($this -> dbName = @mysql_select_db($this -> dbName) == TRUE)
  40. {
  41. return TRUE;
  42. }
  43. else
  44. {
  45. $this -> sqlError();
  46. return FALSE;
  47. }
  48. }
  49. else
  50. {
  51. $this -> sqlError();
  52. return FALSE;
  53. }
  54. }
  55.  
  56. public function sqlQuery($query)
  57. {
  58. $this -> query = $query;
  59. if ((mysql_query($this -> query)) == TRUE)
  60. {
  61. return TRUE;
  62. }
  63. else
  64. {
  65. $this -> sqlError();
  66. return FALSE;
  67. }
  68. }
  69.  
  70. public function sqlFetchOne($query)
  71. {
  72. $this -> query = $query;
  73. if (($this -> result = @mysql_query($this -> query)) == TRUE)
  74. {
  75. $this -> records = mysql_fetch_array($this -> result);
  76. return $this -> records[0];
  77. }
  78. else
  79. {
  80. $this -> sqlError();
  81. return FALSE;
  82. }
  83. }
  84.  
  85. public function sqlFetchArray($query)
  86. {
  87. $this -> query = $query;
  88. if (($this -> result = @mysql_query($this -> query)) == TRUE)
  89. {
  90. $this -> records = mysql_fetch_assoc($this -> result);
  91. return $this -> records;
  92. }
  93. else
  94. {
  95. $this -> sqlError();
  96. return FALSE;
  97. }
  98.  
  99. }
  100.  
  101. public function sqlRows()
  102. {
  103. if ($this -> records_rows = mysql_num_rows($this -> result))
  104. {
  105. return $this -> records_rows;
  106. }
  107. else
  108. {
  109. $this -> sqlError();
  110. return FALSE;
  111. }
  112. }
  113.  
  114. public function getArrayToRand($arrayIn, $limits)
  115. {
  116. $limits[0] = count($limits);
  117. for($i = 1; $i <= $limits[0]; $i++) {
  118. for($x = 1; $x <= $limits[$i]; $x++) {
  119. $arrayOut[]=$arrayIn[$i];
  120. }
  121. }
  122. return $arrayOut;
  123. }
  124.  
  125. public function __destruct()
  126. {
  127. if ($this -> result)
  128. {
  129. mysql_free_result($this -> result);
  130. };
  131. $this -> query,
  132. $this -> result,
  133. $this -> records_rows,
  134. $this -> records,
  135. $this -> dbHost,
  136. $this -> dbUser,
  137. $this -> dbHaslo,
  138. $this -> dbName,
  139. $this -> connection
  140. );
  141. return TRUE;
  142. }
  143. }
  144. ?>
  145.  


a skrypt robi coś takiego
  1. $db = new database; // tworze nowy obiekt bazy danych
  2. wykonuje zapytanie 1 wszystko ok
  3. wykonuje zapytanie 2 wyskakuje powyższy błąd
  4.  
  5.  


Nic innego nie odpowiada zapołączenie z bazą danych

Zauważyłęm że problem występuje tylko wtedy kiedy zapytanie mysql jest w funkcji w jakiejś klasie czyli:
$db = new database;
$db - > connect();

$user = new user;
$user -> load($user); i tutaj właśnie jest zapytanie
$user -> load($user2); jeśli spróbuje wczytać innego użytkownika ponownie to wyskakuje powyższy błąd.


Wniosek mogę używać mojego obiektu bazy danych do wykonania zapytania tylko raz ...

Ten post edytował Hesto 14.11.2013, 15:04:19
Go to the top of the page
+Quote Post
freemp3
post
Post #4





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Mógłbyś pokazać jeszcze jak wygląda metoda load klasy user?
Go to the top of the page
+Quote Post
Hesto
post
Post #5





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


Chciałem tego uniknąć bo nie jest to wszystko eleganckie (IMG:style_emoticons/default/tongue.gif) no ale trudno:
  1. public function load($email)
  2. {
  3. $db = new database;
  4. $db -> sqlFetchArray("SELECT * FROM `orders` WHERE `email` = '$email'");
  5. $this -> id = $db -> records['id'];
  6. $this -> email = $db -> records['email'];
  7. $this -> product = $db -> records['product'];
  8. $this -> status = $db -> records['status'];
  9. }
  10.  


problem rozwiązuje się wtedy kiedy w skrypcie głównym przed wejściem w tą funkcję (load) zamknę połączenie z bazą danych czyli zniszczę obiekt $db, i otworze połączenie ponownie w funkcji load ($db -> connect()(IMG:style_emoticons/default/wink.gif) . Teorytycznie mógłbym tak zrobić, ale przy wczytywaniu 1000 produktów czy użytkowników, łączenie się z bazą danych 1000 razy i rozłączanie, jest nieco żałosne.

Od kilku dni próbuje rozwiązać ten problem i nic nie przychodzi mi do głowy.
Go to the top of the page
+Quote Post
freemp3
post
Post #6





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Funkcje z rodziny mysql_* przyjmują także jako parametr opcjonalny identyfikator połączenia. Mógłbyś we wszystkich wywołaniach tych funkcji podać identyfikator poprawnego połączenia.

Co do namierzenia błędnego połączenia to możesz w metodzie łączącej się z bazą wyrzucić wyjątek w przypadku niepowodzenia, zamiast Twojej funkcji sqlError. W tedy będziesz miał podaną dokładną trase wywołania i bez problemu powinno się znaleźć problem.
Go to the top of the page
+Quote Post
Hesto
post
Post #7





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


Z tym indentyfikatorem połączenia to mogę spróbować jak naprawdę nie będzie wyjścia, tymczasem zobaczę co pokaże wyjątek i wstawię tutaj zaraz.
Go to the top of the page
+Quote Post
freemp3
post
Post #8





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Tak z innej beczki, w jaki sposób przekazujesz dane do logowania do klasy? Zaszyte są na sztywno?
Druga sprawa to za każdym razem jak chcesz odwołać się do bazy tworzysz nową instancję? Przecież to jest nowe połączenie do bazy i strata czasu. Zaimplementuj w klasie wzorzec singleton lub znajdź sposób na przechowywanie jednej instancji klasy globalnie i do niej sie odwołuj. Przyśpieszy to działanie skryptu.
Go to the top of the page
+Quote Post
Hesto
post
Post #9





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


Tak, dane są wpisane w klasie na sztywno.

  1. public function add()
  2. {
  3. $db = new database;
  4. $db -> sqlQuery("INSERT INTO `orders` (email, product, status) VALUES('$this->email','$this->product','$this->status')");
  5. }


wyjątek został wyrzucony tutaj (metoda "add" jest używana jako drugie zapytanie do mysql). Czyli nic to nie dało ponieważ wiedzieliśmy że wyrzuca błąd w drugim zapytaniu z kolei.

Jak już powiedziałem kod nie jest elegancki (IMG:style_emoticons/default/tongue.gif) . Nie jestem profesjonalnym programistą, a samoukiem-amatorem. Jeśli powiesz mi na jakiej zasadzie zaimplementować to inaczej to chętnie to zrobię.

W każdym razie wszystko sprowadza się do jednego pytania: dlaczego wyskakuje błąd 1045 jeśli skrypt wchodzi do jakiejś funkcji i wykonuje tam zapytanie? Jeśli tylko nie wchodzi do funkcji, mogę pisać ile zapytań mi się podoba.

Ten post edytował Hesto 14.11.2013, 16:23:20
Go to the top of the page
+Quote Post
freemp3
post
Post #10





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Dziwne rzeczy to sie dzieją, ale na pewno jest jakieś logiczne wytłumaczenie. Spróbuj zastosować metode gumowej kaczuszki. Co do samej klasy zaś to chyba najszybszym rozwiązaniem będzie zmiana atrybutu connection na statyczny. W tedy w kontrolerze sprawdzasz czy połączenie zostało już nawiązane, jeśli nie tworzysz nowe, jeśli tak wychodzisz z kontrolera.
Jeśli chciało by Ci się trochę pobawić możesz zaimplementować singleton. Przykładowa klasa wygląda mniej więcej tak:
  1. class Singleton
  2. {
  3. /**
  4.   * Instancja klasy
  5.   * @var Singleton
  6.   */
  7. private static $_instance = null;
  8.  
  9. /**
  10.   * Konstruktor - prywatny aby nie było możliwości stworzenia nowej instancji klasy z zewnątrz
  11.   */
  12. private function __construct(){}
  13.  
  14. /**
  15.   * Pobranie instancji klasy
  16.   * @return Singleton
  17.   */
  18. public static function getInstance()
  19. {
  20. if(is_null(self::$_instance))
  21. {
  22. self::$_instance = new Singleton();
  23. }
  24. return self::$_instance;
  25. }
  26. }
Go to the top of the page
+Quote Post
Hesto
post
Post #11





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


Okej, pobawie się jeszcze w Singletonie ale to na pewno nie naprawi mojego problemu. Celowo napisałem temat w dziale "MySQL" ponieważ jestem na 99,99% pewny że problem leży w konfiguracji phpmyadmin. Sam kod PHP nie ma tu nic do rzeczy. Czytałem gdzieś że błąd 1045 wwygląda tak: jeśli MySQL wykonuje zapytanie ponownie to nie wie z którego użytkownika skorzystać dlatego korzysta z pierwszego od góry. Dla pierwszego od góry nie jest ustawione hasło czy coś takiego i występuje błąd. Niestety nie mam pojęcia jak to naprawić.

Próbowałem zmienić hasło wszystkim użytkownikom - nic to nie pomogło. Chciałem zobaczyć tabele user czyli
Select * from mysql.user
Niestety wyskoczyło mi że nie mam uprawnień. Nie rozumiem tylko jakim cudem nie mam uprawnień jeśli było to konto admina. W dodatku w miejscu po zalogowaniu się do phpmyadmin, tam gdzie wybiera się bazę danych mam napisane przy przycisku "utwórz bazę danych", "brak uprawnień". Śmieszne jest to że nie mogę stworzyć nowej bazy danych z poziomu phpmyadmin ale z poziomu DirectAdmin już mogę. Zaczynam przypuszczać że to wszystko ma coś wspólnego z uprawnieniami lub firma hostingowa za którą płacę 30 zł rocznie, z którą są same problemy (ale jest tania) źle mi skonfigurowała serwer. Z drugiej strony przez wiele lat na tym serwerze stała strona w joomli 1.5 + virtuemart i wszystko śmigało bez zarzutu.
Go to the top of the page
+Quote Post
freemp3
post
Post #12





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Cytat
jestem na 99,99% pewny że problem leży w konfiguracji phpmyadmin

PhpMyAdmin jest tylko narzędziem do przeglądania baz danych, tak jak przeglądarka jest narzędziem do przeglądania zasobów internetu (IMG:style_emoticons/default/smile.gif) Jak już to zapewne masz na myśli konfigurację serwera mysql, aczkolwiek to raczej nie ona jest problemem.

Bardzo możliwe, że po poprawieniu połączeń skrypt zacznie działać. Tworzyłeś wiele połączeń i nie podawałeś informacji, z którego będziesz korzystał, więc skrypt mógł głupieć bo nie wiedział. Nie mam pewności, ale zapewne pierwsze połączenie było w globalnym zakresie zmiennych, więc nie był wywoływany destruktor zamykający połączenie. Później pojawiało się drugie połączenie i przy wysłaniu zapytania skrypt nie wie, którego użyć.

Blokada tworzenia bazy danych z phpmyadmina jest częstą praktyką. Nie chodzi o zlośliwość, ale o synchronizacje między tym co jest w panelu klietna, a tym co faktycznie jest na serwerze.

Popraw sposób łaczenia do bazy danych i zobaczymy co będzie się działo.

Ten post edytował freemp3 15.11.2013, 12:10:22
Go to the top of the page
+Quote Post
Hesto
post
Post #13





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 14.11.2013

Ostrzeżenie: (0%)
-----


Skrypt jest prościutki i składa się dosłownie z kilku linijek. Jak sam na pewno zauważyłeś, w klasie database jest funkcja connect() która nie jest wywoływana w konstruktorze. Więc jeśli tworze obiekt typu database to tylko po to aby używać metod do zapytań. Łączę się z bazą tylko jeden jedyny raz więc nie ma możliwości że skrypt nie wie z którego korzystać.
Ja obstawiam że problem leży w uprawnieniach lub błędnej konfiguracji serwera mysql. Niestety nie mam pojęcia jak to naprawić.

Ten post edytował Hesto 15.11.2013, 13:34:26
Go to the top of the page
+Quote Post
freemp3
post
Post #14





Grupa: Zarejestrowani
Postów: 467
Pomógł: 77
Dołączył: 6.09.2008
Skąd: Miechów / Kraków

Ostrzeżenie: (0%)
-----


Gdzieś musi być połączenie wykonywane drugi raz, ponieważ wstawiłeś przecież wyrzucanie wyjątku w przypadku błędu przy połączeniu, czyli w metodze sqlConnect. Poza tym, sam zauważyłeś, że przy usunięciu pierwszej instancji i rozłączeniu z bazą danych drugie połączenie wykonuje się poprawnie (IMG:style_emoticons/default/smile.gif)

Hmm... Może właśnie tutaj jest problem. Próbowałeś wywołać metodę sqlConnect przed zapytaniem powodującym błąd? Jak pisałem wcześniej nie wiem, czy instancja jest trzymana w globalnym zakresie czy w lokalnym, więc strzelałem. Sprawdź drugą możliwość, czyli tworzysz pierwszą instancje ona coś robi, później wychodzisz z zakresu ważności i jest usuwana. Przy drugim wywołaniu nie masz już połączenia bo zostało usunięte wcześniej i mysql próbuje się zalogować na pierwszego użytkownika z brzegu, co skutkuje owym komunikatem.

Ten post edytował freemp3 15.11.2013, 13:56:18
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 04:55