Zend Authentication 'Zend\Authentication\Adapter\DbTable' gives error while authenticating - authentication

I used a simple instruction from
http://framework.zend.com/manual/2.0/en/modules/zend.authentication.adapter.dbtable.html#advanced-usage-by-example for Zend Authentication.
Here is my code:
$adapter = $sm->get('adapter');
$authAdapter = new DbTable($adapter);
$authAdapter -> setTableName('users')->setIdentityColumn('username')->setCredentialColumn('password');
$authAdapter -> setIdentity('admin')-> setCredential('password');
$authAdapter -> authenticate();
The above code generates error as follows:
The supplied parameters to DbTable failed to produce a valid sql statement, please check table and column names for validity.
I know if makes sense to use ZF-Commons and ZF-Users module and not reinvent the wheel... but being relatively new to ZF2 I want to try it myself.

The answer's right there in the error message, Zend\Authentication\Adapter\DbTable expects more than just an adapter as a parameter, it also needs a table name, and the name of the identifier and credential columns...
$authAdapter = new DbTable($dbAdapter,
'tableName',
'identifierColumnName',
'credentialColumnName'
);
This info is covered in the docs, which is always a good starting point -> http://zf2.readthedocs.org/en/release-2.1.4/modules/zend.authentication.adapter.dbtable.html

I know this is an old one and probably you have the answer now. Even though, I will put my answer here for further users. I myself faced lots of similar issues where the tutorials expect us to have some preconditions in place.
This error occur because you are not completely right in the statement to get the DB adapter. You need to call a service management instance with an string defined in your locals or globals configurations. For example:
I have this factory defined in my global.php file:
return array(
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
'db' => array(
'driver' => 'Pdo',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
);
In my local.php I have the credentials and information to reach my DB server as follow:
return array(
'db' => array(
'username' => 'valid_dbusername',
'password' => 'valid_dbpass',
'dsn' => 'mysql:dbname=valid_dbname;host=valid_dbserver',
),
);
This is enough to define my service calle 'Zend\Db\Adapter\Adapter'. Then, to instantiate my Db adapter I have the following lines inside any function in my controller:
if (!$this->adapter) {
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
}
It is important to note adapter here is a class variable. So, it must be defined inside my controller class like:
public $adapter;
This steps are enough to you get an DB adapter. I am assuming you dont have a factory called 'adapter'. This should make your example work.

Related

Yii - Calling api request within CConsole

I have the following issue:
I have a local db with comments and I need to do some actions with some users I'm getting via an API request.
Code is something like this:
class RunCronCommand extends CConsoleCommand {
public function actionIndex() {
...
$comments = Comment::model()->findAll('status = :status', array(':status' => Comment::ACTIVE));
foreach ($comments as $comment) {
$profile = Yii::app()->api->get('/users/'. $comment->user_id . '/getProfile');
}
...
}
When I execute the command I'm getting this error
exception 'CException' with message 'Property "CConsoleApplication.api" is not defined.' in /var/www/core/trunk/common/lib/Yii/base/CComponent.php:131
Any thoughts?
thanks in advance!
Thank you for your reply.
Got it fixed by adding the class into console/config/main.php
'components' => array(
'api' => array(
'class' => 'common.extensions.Api.Api'
),
You will have to rethink the design of the application.
From your example, you might want to use Curl, although I think this might be overkill/
To run an action in a controller, you can use something like
Yii::import('application.modules.moduleName.controllers.ControllerName');
$controller_instance = new ControllerName("Default");
$controller_instance->actionIndex();
Look here for additional information.

how to use Yiic message command with CDbMessageSource

i used to use CPhpMessageSource but i want to try CDbMessageSource i though i just have to change this...
'components' => array(
'message' => array(
// 'class' => 'CPhpMessageSource',
'class' => 'CDbMessageSource',
),
But when i exectute Yiic message to insert translation data in the database it still generate files in protected/messages/"files".php
...
i must have miss one point...
i follow this http://www.yiiframework.com/doc/api/1.1/CDbMessageSource
Even though Yii has a "reader" for database translations, it doesn't have a "writer". What I usually end up doing is writing some code that can populate the tables using the generated translation files.
You can also write a derivated "message" command for Yii and use that to insert in the database directly, it's not that much work:
<?php
Yii::import('system.cli.commands.MessageCommand', TRUE);
class DbMessageCommand extends MessageCommand
{
protected function generateMessageFile($messages,$fileName,$overwrite,$removeOld,$sort)
{
if (preg_match('#/(..)/([^\\/:"*?<>|]+?)\.php$#i', $fileName, $matches))
{
$language = $matches[1];
$category = $matches[2];
foreach ($messages as $message)
{
// $message contains the string, $category has the category and $language is the current language
// Add to your DB here
}
}
}
}
Just create a DbMessageCommand.php file in your commands subdirectory and finish the code and you should be in business.
In short, what this does is use the regular message command to parse the files, but when the generateMessageFile-function is called to write to the php file, it uses a regexp to determine what would be written (it's called per language/category) and adds it in the database.
I haven't included that code, because I don't use the models as they are included in Yii. I have my own CDbMessageSource-variant and my own string tables.

Authentication with CakePHP 2.4 only with sha1?

I got some troubles with the authentication in CakePHP 2.4. I baked a simple App to create a login. I did everything like in the book (Auth and Tutorial). But only sha1 worked. But not sha256 or md5. After searching and testing I came to a solution where I had to change the example code in the book and now it works. But I think, this is not the proper solution.
I did the following in the AppController:
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'passwordHasher' => array(
'className' => 'Simple',
'hashType' => 'sha256'
)
)
)
)
);
}
I tested this with md5, sha1 and sha256. No problem. Login works if the passwords are hashed appropriately.
But I noticed, that adding a user only works with sha1, because this is the default hash.
My User Models beforeSafe function was this (from the book):
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new SimplePasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
}
I thought, that the setting in the AppController is enough, to change the SimplePasswordHasher in this area too. But as it seems, it's not enough. So I changed it to this:
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
to this
$this->data[$this->alias]['password'] = Security::hash(
$this->data[$this->alias]['password'],
'sha256',
true
);
Now everything works like a charm. But my questions:
1) I'm right, that this is necessary or is my code something else wrong?
2) As I know is $xxx->zzz only for Controllers and xxx::zzz() for everywhere and, right?
3) Why do I have to say the Security hash, that it should hash the string with sha256 again, when I said that already in the AppController in general?
1. As far as I know, your approach is right. Might exist a cleaner way, but I am using bcrypt, and the Cookbook says to do something very similar.
2. You can think like you said for a simple explanation. Basically -> is the object-operator, to deal with objects e.g. $this->doEverything. And :: is the scope-resolution-operator which is used to find Class static property or method. And normally you can run this everywhere, e.g., Security::hash().
3. Take a look here, you should probably change your AppController to:
'passwordHasher' => array(
'className' => 'Simple',
'hashType' => 'sha256'
)
to fit on the recomendations. Altough I've tryed this, and didn't changed the SimplePasswordHasher to SHA256. It is a reference that cake seems to ignore somehow. But that is the Simple hasher, intended to simple thing, so you are supposed to do your own approach, or one that fits better to your needs.

Yii ActiveRecord using with() not finding joined record

I have two models: User and UserProfile
Inside the User model, I have defined the following relations:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'userProfile' => array(self::HAS_ONE, 'UserProfile', 'user_id'),
);
}
In UserProfile, I have this relation defined:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'user' => array(self::BELONGS_TO, 'User', 'user_id'),
);
}
Now when I run the following code in my controller:
$user = User::model()->with('userProfile')->findByPK($userId);
$userProfile = $user->userProfile;
print_r($userProfile);
The $userProfile variable is null. I've checked and double-checked the database and code, I've re-read the Yii documentation as well, and seems everything is the way it should be. But it just refuses to work!
Any idea what am I doing wrong?
Generally, you can't have this:
'userProfile' => array(self::HAS_ONE, 'UserProfile', 'user_id'),
and this:
'user' => array(self::BELONGS_TO, 'User', 'user_id'),
both use the user_id key unless both your tables have a user_id key as their primary key. More likely, what you're after is this, like you have:
'userProfile' => array(self::HAS_ONE, 'UserProfile', 'user_id'),
But what that equates to is the SQL statement:
user.id = userProfile.user_id
If that isn't what you want, then you'll need to adjust accordingly. One of the most helpful things for figuring this out is either turning on basic logging of your SQL statements or using the Yii debug toolbar Makes it much easier to see what SQL is being run vs. what you thought would be run.

zend_db standalone

i want to use zend_db standalone cos zend framework is too much for my project but i'm new with it,
is it correct to do this:
$pdoParams = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES
UTF8;');
$params = array(
'host' => 'localhost',
'username' => 'ss_fraat',
'password' => 'jos10',
'dbname' => '_a2hDB',
'driver_options' => $pdoParams
);
try {
$db = Zend_Db::factory('PDO_MYSQL', $params);
//set default adapter
Zend_Db_Table_Abstract::setDefaultAdapter($db);
} catch (Exception $e) {
exit($e->getMessage());
}
//save Db in registry for later use
Zend_Registry::set('dbAdapter', $db);
then in any class do this:
$db = Zend_Registry::get('db');
/** quote to avoid sql injection */
$date = $db->quote('1980-01-01');
$sql = 'SELECT * FROM product WHERE name = ' . $date;
$result = $db->query($sql);
$db->query(); //run a query
i really need to do this
Zend_Db_Table_Abstract::setDefaultAdapter($db);
i get this code from a website,
is it necessary to use Zend_Db_Table_Abstract if i'm not using the full zend framework,
or it is better for example to use this:
$db = Zend_Db::factory( ...options... );
$select = new Zend_Db_Select($db);
what i want is to setup a pdo/mysql connexion in my bootstrap php page and be able to get that db instance in any class without starting a new connexion to execute queries but i'm not sure how to do that use Zend_Db_Table_Abstract or Zend_Db_Select use the registry Zend_Registry::set('dbAdapter', $db) or not
thanks a lot
The purpose of Zend_Db_Table_Abstract is so you can create your own model classes based around the Table Data Gateway design pattern. The idea of that pattern is that you have a class that encapsulates all the sql you would need for interfacing with a table. So the assumption is that you will be creating model classes that extend Zend_Db_Table_Abstract for each table. If you are going to do that, then you will want to call Zend_Db_Table_Abstract::setDefaultAdapter($db) in your setup/bootstrap. Recent versions of ZF provide as an alternative a quick way of getting basic functionality without having to create a custom class definition by just instantiating Zend_Db_Table:
$userTable = new Zend_Db_Table('users');
In summary, none of this particularly has to do with the MVC part of the framework, although some people choose to use Zend_db as the basis for db connections and models, instead of using a more fully featured ORM like Doctrine or Propel.
The other code you provided simply illustrates that you do not need to use Zend_Db_Table_Abstract either -- you can simply setup an instance of a Zend_Db_Adapter and use that instance to call query() or its other methods.