Luckily I found an issue thread in ZfcUser Git Project, and with some tutorial, I come to a solution that work for me. I know it's not the best way, but I want to share for anyone, beginner like me, find a simple way to do authentication and move on to more complex Zend stuff later.
Update: after a while of working with Zend, then I realized that I need not to use Restful for my authentication, I just need to use normal action that will get the POST and return a json file.
use Zend\View\Model\JsonModel;
// Your class
// ...
public function jsonAction(){
// Your code
return new JsonModel(array(
'tag' => 'login',
'success' => 0,
'error' => 1,
'error_msg' => 0,//$this->failedLoginMessage,
));
}
Update 2: If you are thinking about Restful WS, you should investigate some about it first here . As I did from the beginning, trying to use Restful to do authentication is totally wrong. :)
So first, you create a "class AuthRestController extends AbstractRestfulController" like in the tutorial.
Here I do the login and register in a same post method, I use "tag" value in POST to distinguish them.
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
use Zend\Form\Form;
use Customer\Model\Customer;
class AuthRestController extends AbstractRestfulController {
protected $userTable;
protected $authservice;
protected $userService;
protected $loginForm;
protected $failedLoginMessage = 'Incorrect email or password!';
protected $failedRegisterMessage = 'User already existed';
protected $failedMessage = 'Error occured';
public function getAuthService() {
if (!$this->authservice) {
$this->authservice = $this->getServiceLocator()
->get('AuthService');
}
return $this->authservice;
}
public function getList() {
}
public function get($id) {
}
public function create($dataIn) {
// POST
// Translating data
$data = array(
'tag' => $dataIn['tag'],
'identity' => $dataIn['email'],
'credential' => $dataIn['password'],
);
$this->getRequest()->getPost()->set('identity', $data['identity']);
$this->getRequest()->getPost()->set('credential', $data['credential']);
if ($data['tag'] == 'login') {
$form = $this->getLoginForm();
$form->setData($data);
if (!$form->isValid()) {
$this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage($this->failedLoginMessage);
return new JsonModel(array(
'tag' => 'login',
'success' => 0,
'error' => 1,
'error_msg' => $this->failedLoginMessage,
));
} else {
$this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters();
$this->zfcUserAuthentication()->getAuthService()->clearIdentity();
$adapter = $this->zfcUserAuthentication()->getAuthAdapter();
$adapter->prepareForAuthentication($this->getRequest());
$auth = $this->zfcUserAuthentication()->getAuthService()->authenticate($adapter);
if (!$auth->isValid()) {
$this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage($this->failedLoginMessage);
$adapter->resetAdapters();
return new JsonModel(array(
'tag' => 'login',
'success' => 0,
'error' => 1,
'error_msg' => $this->failedLoginMessage,
));
}
$userObject = $this->getUserTable()->findByEmail($data['identity']);
return new JsonModel(array(
'tag' => 'login',
'success' => 1,
'error' => 0,
'uid' => $userObject->uid,
'user' => array(
'name' =>$userObject->display_name,
'email' => $data['identity'],
'created_at' => $userObject->created_at,
'updated_at' => null,
)
));
}
} else if ($data['tag'] == 'register') {
//$prg = $this->prg('user/register', true);
$dataIn['passwordVerify']= $data['credential'];
$service = $this->getUserService();
$user = $service->register($dataIn);
if (!$user) {
// Register not successful. Existing user.
return new JsonModel(array(
'tag' => 'register',
'success' => 0,
'error' => 2,
'error_msg' => $this->failedRegisterMessage,
));
}
// Successful
$userObject = $this->getUserTable()->findByEmail($dataIn['email']);
return new JsonModel(array(
'tag' => 'register',
'success' => 1,
'error' => 0,
'user' => array(
'name' => $userObject->display_name,
'email' => $dataIn['email'],
)
));
}
return new JsonModel(array(
// Error
));
}
public function update($id, $data) {
}
public function delete($id) {
}
public function getUserTable() {
if (!$this->userTable) {
$sm = $this->getServiceLocator();
$this->userTable = $sm->get('Customer\Model\CustomerTable');
}
return $this->userTable;
}
public function getLoginForm() {
if (!$this->loginForm) {
$this->setLoginForm($this->getServiceLocator()->get('zfcuser_login_form'));
}
return $this->loginForm;
}
public function setRegisterForm(Form $registerForm) {
$this->registerForm = $registerForm;
}
public function setLoginForm(Form $loginForm) {
$this->loginForm = $loginForm;
$fm = $this->flashMessenger()->setNamespace('zfcuser-login-form')->getMessages();
if (isset($fm[0])) {
$this->loginForm->setMessages(
array('identity' => array($fm[0]))
);
}
return $this;
}
public function getUserService()
{
if (!$this->userService) {
$this->userService = $this->getServiceLocator()->get('zfcuser_user_service');
}
return $this->userService;
}
}
In order to use some ZfcUser service, you must also need to add some config into YourModule\Module.php file. For me, I copy all the getServiceConfig() method from the ZfcUser\Module.php file (:. (I also do some small modification to my code to make it run, but I don't remember exactly. But I'm sure it's easy, you can do it).
use ZfcUser\Options;
use ZfcUser\Form;
use ZfcUser\Mapper;
use ZfcUser\Validator;
class Module {
public function getAutoloaderConfig(){
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig(){
return include __DIR__ .'/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'invokables' => array(
'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db',
'ZfcUser\Authentication\Storage\Db' => 'ZfcUser\Authentication\Storage\Db',
'ZfcUser\Form\Login' => 'ZfcUser\Form\Login',
'zfcuser_user_service' => 'ZfcUser\Service\User',
'zfcuser_register_form_hydrator' => 'Zend\Stdlib\Hydrator\ClassMethods',
),
'factories' => array(
'zfcuser_module_options' => function ($sm) {
$config = $sm->get('Config');
return new Options\ModuleOptions(isset($config['zfcuser']) ? $config['zfcuser'] : array());
},
// We alias this one because it's ZfcUser's instance of
// Zend\Authentication\AuthenticationService. We don't want to
// hog the FQCN service alias for a Zend\* class.
'zfcuser_auth_service' => function ($sm) {
return new \Zend\Authentication\AuthenticationService(
$sm->get('ZfcUser\Authentication\Storage\Db'),
$sm->get('ZfcUser\Authentication\Adapter\AdapterChain')
);
},
'ZfcUser\Authentication\Adapter\AdapterChain' => 'ZfcUser\Authentication\Adapter\AdapterChainServiceFactory',
'zfcuser_login_form' => function($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new Form\Login(null, $options);
$form->setInputFilter(new Form\LoginFilter($options));
return $form;
},
'zfcuser_register_form' => function ($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new Form\Register(null, $options);
//$form->setCaptchaElement($sm->get('zfcuser_captcha_element'));
$form->setInputFilter(new Form\RegisterFilter(
new Validator\NoRecordExists(array(
'mapper' => $sm->get('zfcuser_user_mapper'),
'key' => 'email'
)),
new Validator\NoRecordExists(array(
'mapper' => $sm->get('zfcuser_user_mapper'),
'key' => 'username'
)),
$options
));
return $form;
},
'zfcuser_change_password_form' => function($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new Form\ChangePassword(null, $sm->get('zfcuser_module_options'));
$form->setInputFilter(new Form\ChangePasswordFilter($options));
return $form;
},
'zfcuser_change_email_form' => function($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new Form\ChangeEmail(null, $options);
$form->setInputFilter(new Form\ChangeEmailFilter(
$options,
new Validator\NoRecordExists(array(
'mapper' => $sm->get('zfcuser_user_mapper'),
'key' => 'email'
))
));
return $form;
},
'zfcuser_user_hydrator' => function ($sm) {
$hydrator = new \Zend\Stdlib\Hydrator\ClassMethods();
return $hydrator;
},
'zfcuser_user_mapper' => function ($sm) {
$options = $sm->get('zfcuser_module_options');
$mapper = new Mapper\User();
$mapper->setDbAdapter($sm->get('zfcuser_zend_db_adapter'));
$entityClass = $options->getUserEntityClass();
$mapper->setEntityPrototype(new $entityClass);
$mapper->setHydrator(new Mapper\UserHydrator());
$mapper->setTableName($options->getTableName());
return $mapper;
},
),
);
}
}
To test Restful web service, I use this tool: Postman for Chrome.
My module code here.
Hope it can help.
Why do you believe using REST for Authentication is 'totally wrong' ?
ReplyDeleteSee here for why that's not the case necessarily, http://stackoverflow.com/questions/319530/restful-authentication
Oh, thank you for giving me some more information :).
DeleteI meant the way I used REST for my authentication is wrong. The way I did is not good, so people should avoid do like me.
Ban oi co ban hoan chinh cua module o tren khong ban. Module ban minh down ve bi thieu class customer
ReplyDelete