MongoDB PHP Driver Fails to Connect and Authenticate - php

I have set up for the first time the authentication for MongoDB. I have two users: 'admin', (set as root in the 'admin' database) and 'testUser' which is set up as 'dbAdmin' in the 'testDatabase'.
When I use mongo shell to login using the following command everything works:
mongo -u testUser -p abcd1234 --authenticationDatabase testDatabase
On the PHP's end, I have the following code:
<?php
class DBConnection {
const HOST = '1.1.1.1';
const PORT = 27017;
const DBNAME = 'testDatabase';
const USERNAME = 'testUser';
const PASSWORD = 'abcd1234';
private static $instance;
public $connection;
public $database;
private function __construct() {
if (!extension_loaded('mongo')) die("MongoDB is not installed!");
try {
$this->connection = new MongoClient('mongodb://'.self::HOST.':'.self::PORT.'/'.self::DBNAME, array('username' => self::USERNAME, 'password' => self::PASSWORD));
$this->database = $this->connection->selectDB(self::DBNAME);
} catch (MongoConnectionException $e) {
throw $e;
}
}
static public function instantiate() {
if (!isset(self::$instance)) {
$class = __CLASS__;
self:: $instance = new $class;
}
return self::$instance;
}
public function getCollection($name) {
return $this->database->selectCollection($name);
}
public function execute($code) {
return $this->database->execute($code);
}
}
?>
Naturally, host (as well as the db name, username and password) are obfuscated. I have verified multiple time that there is not a typo in the credentials. I have also verified that I can connect to the database from a remote shell, similar to how this script connects.
Still, I always get this error:
PHP Fatal error: Uncaught exception 'MongoConnectionException' with
message 'Failed to connect to: 1.1.1.1:27017: Authentication
failed on database 'testDatabase' with username 'testUser': auth failed' in
/var/www/html/wip/include/mongoConnect.php:17 Stack trace:
0 /var/www/html/wip/include/mongoConnect.php(17): MongoClient->__construct('mongodb://1.1...', Array)
1 /var/www/html/wip/include/mongoConnect.php(27): DBConnection->__construct()
2 /var/www/html/wip/migration/migrate.php(85): DBConnection::instantiate()
3 {main} thrown in /var/www/html/wip/include/mongoConnect.php on line 17
Credentials for both users are in SCRAM-SHA-1.
Any idea what is causing this connection issue?

You can try to change the way of logging in
$m = new MongoClient("mongodb://${username}:${password}#localhost");
Take a look at here:
http://php.net/manual/en/mongo.connecting.auth.php

Related

mysqli::__construct(): (HY000/1045): Access denied for user 'lfc_site'#'localhost' (using password: YES)

I am switching my hosting platform from cPanel to Plesk and seem to be having some issues with a script on one of my sites. The main site is running on the latest version of Joomla and makes it's database connection with no errors. I have an external script that I run on a cron job however that does not seem to connect. I get this error:
mysqli::__construct(): (HY000/1045): Access denied for user 'lfc_site'#'localhost' (using password: YES)
I have to assume that it has to do with my connection class so I will post it here:
I have a cofig.ini that contains the DB login credentials.
[database]
username = database_user
password = ******
dbname = database_name
then my connection class is this:
<?php
//Database connection class
class Db {
protected static $connection;
public function connect() {
if(!isset(self::$connection)) {
global $config;
self::$connection = new mysqli('localhost:3306',$config['username'],$config['password'],$config['dbname']);
}
if(self::$connection === false) {
return false;
}
return self::$connection;
}
public function query($query) {
$connection = $this -> connect();
$result = $connection -> query($query);
return $result;
}
public function select($query) {
$rows = array();
$result = $this -> query($query);
if($result === false) {
return false;
}
while ($row = $result -> fetch_assoc()) {
$rows[] = $row;
}
return $rows;
}
public function error() {
$connection = $this -> connect();
return $connection -> error;
}
public function quote($value) {
$connection = $this -> connect();
return "'" . $connection -> real_escape_string($value) . "'";
}
}
?>
and then finally my script runs the query as such....
<?php
require_once('/var/www/vhosts/user/httpdocs/db.php');
$config = parse_ini_file('/var/www/vhosts/user/httpdocs/config.ini');
$db = new Db();
$rows = $db -> select('
SELECT *
FROM milestones
WHERE status != "arrived"
AND departure_time BETWEEN (NOW() - INTERVAL 12 HOUR)
AND (NOW() + INTERVAL 12 HOUR)
AND type = "4"
');
?>
I am guessing that maybe there is a module not enabled that is prohibiting this script from establishing a connection properly, as like I said, the Joomla script seems to connect without issue using the exact same credentials?
What do you mean by "external script"?
By the output you gave I assume it is located on the same machine as the Joomla installation.
The problem most likely doesn't lie with your credentials (if they work for Joomla and you have double-checked them) but with the hostname you provide or a server configuration or MariaDB user (lfc_site) permissions.
You can try to change localhost in your code to 127.0.0.1 and see if it makes any difference.
If not, please SSH into your server and provide output of
plesk db and then SELECT user, host FROM mysql.user WHERE user = 'lfc_site';
and grep bind /etc/mysql/my.cnf
for further investigations.

What exactly a PDO statement will return when no rows match the query criteria?

I'm building a class to login users, so everything works great on localhost, but when i upload the files to the server, the code doesn't work as espected...
I checked this question Value return when no rows in PDO but i couldn't make it work...
My goal is to be able to retrieve the data from the Database and then check either the password is correct or not. I need 3 feedbacks:
User Doesn't exist
Pass/User combination doesn't match.
All good, proceed and login the user.
First I call the class:
$a = $login->login_user_admin($_POST['user']);
Then I get the result: Updated full class & connection
class Database extends PDO
{
private $dbname = "xxx";
private $host = "localhost";
private $user = "xxx";
private $pass = "xxx";
private $port = 5432;
private $dbh;
public function __construct()
{
try {
$this->dbh = parent::__construct("pgsql:host=$this->host;port=$this->port;dbname=$this->dbname;user=$this->user;password=$this->pass");
} catch(PDOException $e) {
echo $e->getMessage();
}
}
public function close_con()
{
$this->dbh = null;
}
}
class Users
{
private $con;
public function __construct()
{
$this->con = new Database();
$this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$this->con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
public function login_user_admin($user)
{
try{
$stmt = $this->con->prepare("SELECT name,salt,pass FROM users.users_admin WHERE name=? LIMIT 1");
$stmt->execute(array($user));
$this->con->close_con();
return $stmt->fetch(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
echo $e->getMessage();
}
}
}
Finally I process:
$data = [];
if ($a!=true) {
$data['success'] = false;
$data['message'] = 'User doesn't exist';
}else{
//All good proceed to chk the password.
}
I tried with empty and isset... didn't work on server either, they all work on local tough. I also try using fetchAll() and checking the empty string but i couldn't make it.
I went to check on the PHP versions on the server and local and they both running on 5.5 so I run out of ideas for now and I will appreciate some help on this.
Update!
I upload a file with only this code to check if I am getting any result from the database and I realize I am not,
include '../functions/functions.php';
$login = new Users();
$a = $login->login_user_admin("emirocast");
print_r($a);
var_dump($a);
The only user in the database right now is "emirocast" so i should get the result but i get a bool(false) instead.
The other thing I noticed is that the server is running Postgresql 8.4 and I am running 9.1 locally. Can this be the problem here?

PDO Creation Fails when Connecting to Remote MySQL Server

My friend and I are working on a website, and I am trying to install a build of it on my machine. It is already running live on the server, I just can't seem to connect from my local machine. When I do I get the following error:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [1045]
Access denied for user 'myusername'#'adsl-client.example.net' (using password: YES)' in /Users/myname/Sites/mysitefolder/req/connect.php:25
Stack trace: #0 /Users/myname/Sites/mysitefolder/req/connect.php(25): PDO->__construct('mysql:host=mysq...', 'myusername', 'mypassword')
#1 /Users/myname/Sites/burn-after-reading/inc/header.php(9): ConnectionFactory->getConnection()
#2 /Users/myname/Sites/burn-after-reading/index.php(79): include('/Users/myna...')
#3 {main} thrown in /Users/myname/Sites/mysitefolder/req/connect.php on line 25
Here is the file I am trying to connect from, connect.php
<?php
class ConnectionFactory
{
var $dbhost = 'mysql.mysitename.io';
var $dbname = 'my_database_name';
var $dbusername = 'myusername';
var $dbpassword = 'mypassword';
private static $factory;
public static function getFactory()
{
if (!self::$factory)
self::$factory = new ConnectionFactory();
return self::$factory;
}
public function getConnection()
{
$conn = new PDO("mysql:host={$this->dbhost};dbname={$this->dbname}",
$this->dbusername,
$this->dbpassword);
return $conn;
}
public function getConnectionNoName()
{
$connNoName = new PDO(
"mysql:host={$this->dbhost}",
$this->dbusername,
$this->dbpassword
);
return $connNoName;
}
}
For security reason you need to add your IP address to the list of allowed remote mysql connections.

can't connect to db through another class

I have an issue that I can't figure out. I have a class Database which if I use it directly I connect to db regularly. I have another class Categories and I want to call a Database object. The problem is that if I call $db->connect in categories does not work. I tried call mysql_connect directly in Categories and it works fine!
Why can't I use $db->connect (the error is Access denied for user 'user'#'0.0.0.0' (using password: YES).
My code in class Database is:
public function connect($new_link=false){
$this->link_id = #mysql_connect($this->server,$this->user,$this->pass,$new_link);
echo "<br/>link_id = ".$this->link_id;
if (!$this->link_id){//open failed
$this->oops("Could not connect to server: <b>$this->server</b>.");
}
else{
echo "Connected to server <br/>";
}
if(!#mysql_select_db($this->database, $this->link_id)){//no database
$this->oops("Could not open database: <b>$this->database</b>.");
}
else{
echo "Database opened <br/>";
}
// unset the data so it can't be dumped
$this->server='';
$this->user='';
$this->pass='';
$this->database='';
}#-#connect()
My code in class Category is:
public static function selectAll() { // SELECT All Function
$db = Database::obtain();
// connect to the server
$db->connect();
$sql = "SELECT * FROM productCategory";
$rows = $db->fetch_array($sql);
return $rows;
}
Database::obtain code
public static function obtain($server=null, $user=null, $pass=null, $database=null){
if (!self::$instance){
self::$instance = new Database($server, $user, $pass, $database);
}
return self::$instance;
}#-#obtain()
Am I doing sth wrong, that I can't see?
Well, the error message is "Access denied for user 'user'#'0.0.0.0'"
That means when you instantiate your class with $db = Database::obtain(); You don't set the values for server, user, pass, database. Probably the class Database implements a singleton pattern, and the method obtain() just returns the instance without any properties set.

Should objects be created chronologically as class defined?

I am having a strange error while creating objects. While I create an objects in chronological orders as classed defined, it is going on good. But when I change the order or object creation, it gives error.
The classes I am using are as follows:
<?php
class dbClass{
private $dbHost, $dbUser, $dbPass, $dbName, $connection;
function __construct(){
require_once("system/configuration.php");
$this->dbHost = $database_host;
$this->dbUser = $database_username;
$this->dbPass = $database_password;
$this->dbName = $database_name;
}
function __destruct(){
if(!$this->connection){
} else{
mysql_close($this->connection);
}
}
function mysqlConnect(){
$this->connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass) or die("MySQL connection failed!");
mysql_select_db($this->dbName,$this->connection);
}
function mysqlClose(){
if(!$this->connection){
} else{
mysql_close($this->connection);
}
}
}
class siteInfo{
private $wTitle, $wName, $wUrl;
function __construct(){
require_once("system/configuration.php");
$this->wTitle = $website_title;
$this->wName = $website_name;
$this->wUrl = $website_url;
}
function __destruct(){
}
function showInfo($keyword){
if($keyword=="wTitle"){
return $this->wTitle;
}
if($keyword=="wName"){
return $this->wName;
}
if($keyword=="wUrl"){
return $this->wUrl;
}
}
}
?>
The problem is when I create objects in the following order, it is working perfectly:
include("system/systemClass.php");
$dbConnection = new dbClass();
$dbConnection -> mysqlConnect();
$siteInfo = new siteInfo();
But if I change the order to following
include("system/systemClass.php");
$siteInfo = new siteInfo();
$dbConnection = new dbClass();
$dbConnection -> mysqlConnect();
It gives error!
Warning: mysql_connect() [function.mysql-connect]: Access denied for user '#####'#'localhost' (using password: NO) in /home/#####/public_html/#####/system/systemClass.php on line 19
MySQL connection failed!
Your problem comes from the unconventional use of a configuration file that is read ONCE, but should be used in all classes.
When you instantiate the dbclass first, the configuration is read, probably variables get assigned, and you use these in the constructor.
After that, instantiating siteinfo will not read that file again, which is less harmful, because you only end up with an empty object that does return a lot of null, but does work.
The other way round, you get a siteinfo object with all the info, but a nonworking dbclass.
My advice: Don't use a configuration file that way.
First step: Remove the require_once - you need that file to be read multiple times.
Second step: Don't read the file in the constructor. Add one or more parameters to the constructor function and pass the values you want to be used from the outside.
Info: You can use PHP code files that configure stuff, but you shouldn't define variables in them that get used outside. This will work equally well:
// configuration.php
return array(
'database_host' => "127.0.0.1",
'database_user' => "root",
// ...
);
// using it:
$config = require('configuration.php'); // the variable now has the returned array

Categories