I am trying to implement Custom authentication via SOAP webservice
as per Refering links
http://it-cook-de.blogspot.in/2013/07/zend-framework-2-custom-authentication-with-soap-webservice-part-1.html
http://samsonasik.wordpress.com/2012/10/23/zend-framework-2-create-login-authentication-using-authenticationservice-with-rememberme/#comment-6117
Now getting error as
Code :
<?php
namespace Application\Adapter;
use Zend\Authentication\Adapter\AdapterInterface;
use Zend\Authentication\Result;
use Zend\Soap\Client;
use Zend\Soap\Client\DotNet as DotNet;
class SoapAuthenticationAdapter implements AdapterInterface
{
//:TODO: move to configuration
//private $module = 'my_application_name_in_auth_system';
private $module = 'student';
//:TODO: move to configuration
// private $uri = 'full_url_to_soap_webservice_of_auth_system';
private $uri = 'http://ip/Service/student.svc?wsdl';
//:TODO: move to configuration
//private $location = 'full_url_to_soap_webservice_of_auth_system';
private $location = 'http://ip/Service/student.svc?wsdl';
protected $username;
protected $password;
protected $customercode;
function __construct()
{
}
public function authenticate()
{
$client = new DotNet($this->uri);
$param=array("customercode"=>$this->customercode,"username"=>$this->username,"password"=>$this->password);
$result = $client->call('ValidateUser',array($param));
if ($result) {
$this->permissions = $param;
return $this->getResult(Result::SUCCESS, $this->permissions, 'SUCCESS');
} else {
return $this->getResult(Result::FAILURE_CREDENTIAL_INVALID, null, 'FAILURE_CREDENTIAL_INVALID');
}
} catch (\SoapFault $e) {
// switch ($e->getMessage()) {
return $this->getResult(Result::FAILURE_UNCATEGORIZED, null, $e->getMessage());
// }
}
}
public function setIdentity($username)
{
$this->username = $username;
}
public function setCredential($password)
{
$this->password = $password;
}
public function setCustomerCode($customercode)
{
$this->customercode =$customercode;
}
private function getResult($type, $identity, $message)
{
return new Result($type, $identity, array(
$message
));
}
}
/////In IndexController
public function getAuthService()
{
if (! $this->authservice) {
$this->authservice = $this->getServiceLocator()
->get('SoapAuthenticationService');
}
return $this->authservice;
}
public function someAction()
{
$request = $this->getRequest();
if ($request->isPost()){
$this->getAuthService()->getAdapter()
->setIdentity($request->getPost('username'))
->setCredential($request->getPost('password'))
->setCustomerCode($request->getPost('customercode'));
$result = $this->getAuthService()->authenticate();
foreach($result->getMessages() as $message)
{
//save message temporary into flashmessenger
$this->flashmessenger()->addMessage($message);
}
if ($result->isValid()) {
$redirect = 'home';
//check if it has rememberMe :
if ($request->getPost('rememberme') == 1 ) {
$this->getSessionStorage()
->setRememberMe(1);
//set storage again
$this->getAuthService()->setStorage($this->getSessionStorage());
}
$this->getAuthService()->setStorage($this->getSessionStorage());
$this->getAuthService()->getStorage()->write($request->getPost('username'));
}
else
{
$redirect ='login';
}
return $this->redirect()->toRoute($redirect);
}
in module.php
public function getServiceConfig()
{
return array(
'factories' => array(
//Add the following lines
'Application\Model\SoapAuthenticationStorage' => function($sm){
return new SoapAuthenticationStorage('student');
},
'SoapAuthenticationService' => function($sm) {
$authAdapter = new SoapAuthenticationAdapter();
$authService = new AuthenticationService();
$authService->setAdapter($authAdapter);
$authService->setStorage($sm->get('Application\Model\SoapAuthenticationStorage'));
return $authService;
}
)
);
}
Any help to solve this
Each of the set methods in your adapter need to return $this in order to allow you to chain method calls together (this is called a 'fluent interface'). E.g.:
public function setIdentity($username)
{
$this->username = $username;
return $this;
}
That should fix the error you're getting.
Related
I am currently in the development of a module prestashop and I meet a problem. I created a new hook for my module and I add an admin controller in my module that execute this hook I add the function that calls the hook and that uses a template. Except that the template does not appear I have an empty page. Here is the code I did:
My module:
<?php
if (!defined('_PS_VERSION_'))
exit;
/* Checking compatibility with older PrestaShop and fixing it */
if (!defined('_MYSQL_ENGINE_'))
define('_MYSQL_ENGINE_', 'MyISAM');
require_once(_PS_MODULE_DIR_.'blockobjectif/classes/Objectif.php');
class blockobjectif extends Module
{
public function __construct()
{
$this->name = 'blockobjectif';
$this->tab = 'front_office_features';
$this->version = '1.0';
$this->author = 'Athor Athor';
$this->bootstrap = true;
$this->need_instance = 0;
$this->ps_versions_compliancy['min'] = '1.5';
$this->ps_versions_compliancy['max'] = '1.6';
parent::__construct();
$this->displayName = $this->l('Objectifs');
$this->description = $this->l('Définie des objectifs aux clients');
}
public function install()
{
$sql = array();
include(dirname(__FILE__).'/sql/install.php');
foreach ($sql as $s)
if (!Db::getInstance()->execute($s))
return false;
$class = 'AdminObjectif';
$tab = new Tab();
$tab->class_name = $class;
$tab->module = $this->name;
$tab->id_parent = (int) Tab::getIdFromClassName('AdminParentCustomer');
$langs = Language::getLanguages(false);
foreach ($langs as $l) {
$tab->name[$l['id_lang']] = $this->l('Objectifs');
}
$tab->save();
return parent::install()
&& $this->registerHook('displayCustomerAccount')
&& $this->registerHook('displayAdminObjectifs');
}
public function uninstall($delete_params = true)
{
$sql = array();
include(dirname(__FILE__).'/sql/uninstall.php');
foreach ($sql as $s)
if (!Db::getInstance()->execute($s))
return false;
$moduleTabs = Tab::getCollectionFromModule($this->name);
if (!empty($moduleTabs)) {
foreach ($moduleTabs as $moduleTab) {
$moduleTab->delete();
}
}
if (!parent::uninstall())
return false;
return true;
}
public function hookDisplayCustomerAccount($params)
{
ddd($params);
}
public function hookDisplayAdminObjectifs($params)
{
return $this->display(__FILE__, 'admin-obj.tpl');
}
}
My AdminObjectifController:
<?php
class AdminObjectifController extends ModuleAdminController
{
public function __construct()
{
$this->bootstrap = true;
$this->table = 'objectifs';
$this->className = 'Objectif';
parent::__construct();
Hook::exec('displayAdminProductsExtra');
}
}
Result:
I do not see where the problem comes from ...
Thank you for your help
This is not the right method to display a backoffice controller template.
Here is what you should try:
<?php
class AdminObjectifController extends ModuleAdminController
{
public function __construct()
{
$this->bootstrap = true;
$this->table = 'objectifs';
$this->className = 'Objectif';
parent::__construct();
}
public function initContent()
{
$tpl = $this->context->smarty->createTemplate($this->getTemplatePath() . 'admin-obj.tpl', $this->context->smarty);
$tpl->assign(array(
'my_var' => "test"
));
$this->content .= $tpl->fetch();
parent::initContent();
}
}
Note that your admin-obj.tpl file should be placed under views/templates/admin/admin-obj.tpl inside your module.
Is it possible to nest aggregate hydrators? If i have the following classes:
class Appointment{
public date;
public startTime;
public endTime;
public User; //* #var User */
}
class User{
public Location; //* #var Location*/
}
...being populated with the following AggregateHydrator (created from a factory):
class AppointmentModelHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$serviceManager = $serviceLocator->getServiceLocator();
$arrayHydrator = new ArraySerializable();
$arrayHydrator->addStrategy('date', new DateTimeStrategy())
->addStrategy('endTime', new TimeStrategy())
->addStrategy('startTime', new TimeStrategy());
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($arrayHydrator);
$aggregateHydrator->add($serviceLocator->get('Hydrator\User'));
return $aggregateHydrator;
}
}
With the UserHydratorFactory looking like:
class UserHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$sm = $serviceLocator->getServiceLocator();
$userHydrator = new UserHydrator($sm->get('User\Mapper'));
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($userHydrator );
$aggregateHydrator->add($sm->get('HydratorManager')->get('Hydrator\User\Location'));
return $aggregateHydrator;
}
}
This is throwing an expection as the model is being returned as null, but if i comment out adding the Location hydrator to the User hydrator, it works fine (albeit without location data loaded). So i was wondering if aggregate hydrators are able to be nested?
It is not built-in, but doable.
namespace Hydrator;
use Zend\Stdlib\Hydrator\HydratorInterface;
class NestedHydrator implements HydratorInterface
{
protected $inner_hydrator;
private $empty;
public function __construct ($inner_hydrator, $empty)
{
$this->inner_hydrator = $inner_hydrator;
$this->empty = $empty;
}
public function extract ($object)
{
return [
$this->getPath() => $this->inner_hydrator->extract ($object->{$this->getPath()})
];
}
public function hydrate (array $data, $object)
{
$object->{$this->getPath()} = $this->inner_hydrator->hydrate ($data [$this->getPath()], $this->empty);
return $object;
}
protected function getPath ()
{
return get_class ($this->empty);
}
}
And then:
$u = new User();
$u->Location = "4 Clinton Rd.";
$a = new Appointment();
$a->date = "yesterday";
$a->startTime = "7:00";
$a->endTime = "8:00";
$a->User = $u;
$h = new AggregateHydrator();
$h->add (new ObjectProperty());
$nested = new \Hydrator\NestedHydrator(new ObjectProperty(), new User());
$h->add ($nested);
$data = $h->extract ($a);
$b = $h->hydrate ($data, new Appointment());
$this->assertEquals ($a, $b);
I am working on Album Application in zf3.I added acl functionality to the application like this:
AlbumController.php
class AlbumController extends AbstractActionController
{
protected $role;
public function onDispatch(\Zend\Mvc\MvcEvent $e)
{
$userSession = new Container('user');
if (!isset($userSession->email)) {
return $this->redirect()->toRoute('login');
}
else {
$this->role = $userSession->role;
parent::onDispatch($e);
}
}
public function checkPermission($role,$action)
{
if($role == 'admin'){
$acl = new Acl();
if ($acl->isAllowed('admin', 'AlbumController', $action)) {
return true;
}
}
return false;
}
public function editAction()
{
$action = 'edit';
$permission = $this->checkPermission($this->role,$action);
if (!$permission) {
$this->flashMessenger()->addMessage('<div class="alert alert- danger" role="alert"><b>You dont have the privilege to edit!!</b></div>');
return $this->redirect()->toRoute('album');
}
$id = (int) $this->params()->fromRoute('id', 0);
if (0 === $id) {
return $this->redirect()->toRoute('album', ['action' => 'add']);
}
try {
$album = $this->table->getAlbum($id);
} catch (\Exception $e) {
return $this->redirect()->toRoute('album', ['action' => 'index']);
}
$form = new AlbumForm();
$form->bind($album);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
$viewData = ['id' => $id, 'form' => $form];
if (! $request->isPost()) {
return $viewData;
}
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
$edit = $request->getPost('submit', 'Cancel');
if($edit == 'Cancel'){
$this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Cancelled by User...!!</b></div>');
return $this->redirect()->toRoute('album');
}
if (! $form->isValid()) {
$this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Failed to Update...!!</b></div>');
return $viewData;
}else{
$this->table->saveAlbum($album);
$this->flashMessenger()->addMessage('<div class="alert alert-success" role="alert"><b>Record Updated Successfully...!!</b></div>');
}
// Redirect to album list
return $this->redirect()->toRoute('album', ['action' => 'index']);
}
}
This is working perfectly fine,now i want to move the onDispatch function to Module.php but don't know how to implement it.Can someone please help me
Module.php
<?php
namespace Album;
use Album\Controller\AlbumController;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Album\Model\LoginTable;
class Module implements ConfigProviderInterface
{
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}
public function getServiceConfig()
{
return [
'factories' => [
AlbumTable::class => function($container) {
$tableGateway = $container->get(Model\AlbumTableGateway::class);
return new AlbumTable($tableGateway);
},
Model\AlbumTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
Model\LoginTable::class => function($container) {
$tableGateway = $container->get(Model\LoginTableGateway::class);
$table = new LoginTable($tableGateway);
return $table;
},
Model\LoginTableGateway::class => function ($container){
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
return new TableGateway('login', $dbAdapter, null, $resultSetPrototype);
}
],
];
}
public function getControllerConfig()
{
return [
'factories' => [
Controller\AlbumController::class => function($container) {
return new Controller\AlbumController($container->get(Model\AlbumTable::class));
},
Controller\LoginController::class => function($container) {
return new Controller\LoginController($container->get(Model\LoginTable::class));
},
Controller\LogoutController::class => function($container){
return new Controller\LogoutController($container->get(Model\LoginTable::class));
},
],
];
}
}
This is how I implemented it. In your Module.php, add a listener on EVENT_DISPATCH, with a closure as callback that will call your middleware class authorization :
class Module implements ConfigProviderInterface
{
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}
public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$eventManager = $app->getEventManager();
$serviceManager = $app->getServiceManager();
// Register closure on event DISPATCH, call your checkProtectedRoutes() method
$eventManager->attach(MvcEvent::EVENT_DISPATCH, function (MvcEvent $e) use ($serviceManager) {
$match = $e->getRouteMatch();
$auth = $serviceManager->get(Middleware\AuthorizationMiddleware::class);
$res = $auth->checkProtectedRoutes($match);
if ($res instanceof Response) {
return $res;
}
}, 1);
// Init ACL : could be improved
$this->initAcl($e);
}
You should have an AuthorizationMiddlewareFactory (call it as you want):
<?php
namespace MyModule\Factory;
use Interop\Container\ContainerInterface;
use MyModule\Middleware\AuthorizationMiddleware;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;
class AuthorizationMiddlewareFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$authService = $container->get(AuthenticationService::class);
$acl = $container->get('Acl'); // II init it in bootstrap(), could be improved
$response = $container->get('Response');
$baseUrl = $container->get('Request')->getBaseUrl();
$authorization = new AuthorizationMiddleware($authService, $acl, $response, $baseUrl);
return $authorization ;
}
}
And your AuthorizationMiddleware class:
<?php
namespace MyModule\Middleware;
use Symfony\Component\VarDumper\VarDumper;
use Zend\Authentication\AuthenticationService;
use Zend\Http\PhpEnvironment\Response;
use Zend\Permissions\Acl\Acl;
use Zend\Router\RouteMatch;
class AuthorizationMiddleware
{
private $authService ;
private $acl;
private $response;
private $baseUrl;
/**
* AuthorizationMiddleware constructor.
* #param AuthenticationService $authService
* #param Acl $acl
* #param Response $response
* #param $baseUrl
*/
public function __construct(AuthenticationService $authService, Acl $acl, Response $response, $baseUrl)
{
$this->authService = $authService;
$this->acl = $acl;
$this->response = $response;
$this->baseUrl = $baseUrl;
}
public function checkProtectedRoutes(RouteMatch $match)
{
if (! $match) {
// Nothing without a route
return null ;
}
// Do your checks...
}
It can be improved, but you have the idea... See also this Question and the answers: ZF3 redirection after ACL authorization failed
I want make possible for user change the language of the webside. In the Module.php I wrote this:
public function onBootstrap(MvcEvent $e)
{
$e->getApplication()->getServiceManager('translator');
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$eventManager->attach(\Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'bootstrapSession'), 10);
$config = $this->getConfig();
\Locale::setDefault('de');
\Zend\Validator\AbstractValidator::setDefaultTranslator(
$e->getApplication()
->getServiceManager()
->get('translator')
);
if ($session->language !== NULL)
{
$e->getApplication()->getServiceManager()->get('translator')->setLocale($session->language);
}
public function bootstrapSession()
{
$config = $this->getConfig();
$sessionConfig = new Session\Config\SessionConfig();
$sessionConfig->setOptions($config['session']);
$sessionManager = new Session\SessionManager($sessionConfig);
$sessionManager->start();
var_dump($sessionManager);
Session\Container::setDefaultManager($sessionManager);
}
public function getServiceConfig()
{
var_dump('halloo');
return array(
'factories' => array(
'session' => function() {
$session = Session\Container::getDefaultManager()->getStorage();
return $session;
},
),
);
}
In the IndexController.php I want to change the language and get it after in the module. So that the language changes.
Here is my action:
public function enAction()
{
$session = $this->getServiceLocator()->get('session');
$session->language = 'en';
return $this->redirect()->toRoute('home');
}
The browser shows no error but the language doesn't change. Does someone see a error and can help me?
Module.php
public function onBootstrap(MvcEvent $e){
// session container
$sessionContainer = new \Zend\Session\Container('locale');
// test if session language exists
if(!$sessionContainer->offsetExists('mylocale')){
// if not use the browser locale
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
$sessionContainer->offsetSet('mylocale', \Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']));
}else{
$sessionContainer->offsetSet('mylocale', 'en_US');
}
}
// translating system
$translator = $serviceManager->get('translator');
$translator ->setLocale($sessionContainer->mylocale)
->setFallbackLocale('en_US');
$mylocale = $sessionContainer->mylocale;
Controller
Just change the language from controller
/**
*
* #return \Zend\View\Model\ViewModel
*/
public function changelocaleAction(){
// disable layout
$result = new ViewModel();
$result->setTerminal(true);
// variables
$event = $this->getEvent();
$matches = $event->getRouteMatch();
$myLocale = $matches->getParam('locale');
$redirect = $matches->getParam('redirecturl', '');
// translate
$sessionContainer = new Container('locale');
switch ($myLocale){
case 'fr_FR':
break;
case 'en_US':
break;
default :
$myLocale = 'en_US';
}
$sessionContainer->offsetSet('mylocale', $myLocale);
// redirect
switch ($redirect){
case '':
$this->redirect()->toRoute('home');
break;
default :
$this->redirect()->toUrl(urldecode($redirect));
}
return $result;
}
From Zend Framework Multi Language Integration Steps
I am trying to implement View Strategy in ZF2.
As far as the basic setup, everything seem to be working fine except that ViewEvent Renderer is always null, thus the renderer never gets injected to the Strategy, and TemplateResolver still requests a template and displays the following error.
PhpRenderer::render: Unable to render template "api/api/get"; resolver could not resolve to a file'
I have even tried to copy the code JsonModel and JsonStrategy from ZF2, and still get the same result.
ViewYamlStrategy.php
public function selectRenderer(ViewEvent $e)
{
$renderer = $e->getRenderer(); // Always return null
}
module.php
public function getServiceConfig()
{
return ['factories' => [
'ViewYamlRenderer' => "Namespace\Mvc\Service\ViewYamlRendererFactory",
'ViewYamlStrategy' => "Namespace\Mvc\Service\ViewYamlStrategyFactory",
],
];
}
module.config.php
'view_manager' => [
'strategies' => [
'ViewYamlStrategy'
],
],
controller
public function getList()
{
return new YamlModel($data);
}
ViewYamlStrategy.php
function __construct(ViewYamlRenderer $renderer)
{
$this->renderer = $renderer;
}
public function attach(EventManagerInterface $events, $priority = 1)
{
$this->listeners[] = $events->attach(ViewEvent::EVENT_RENDERER, [$this, "selectRenderer"], $priority);
$this->listeners[] = $events->attach(ViewEvent::EVENT_RESPONSE, [$this, "injectResponse"], $priority);
}
public function selectRenderer(ViewEvent $e)
{
$renderer = $e->getRenderer();
if ($this->renderer !== $renderer) {
return;
}
}
public function injectResponse(ViewEvent $e)
{
$renderer = $e->getRenderer(); // Always null
if ($this->renderer !== $renderer) {
return;
}
$result = $e->getResult();
$response = $e->getResponse();
$response->setContent($result);
}
ViewYamlRenderer.php
public function render($nameOrModel, $values = null)
{
return $nameOrModel->serialize();
}
public function setResolver(\Zend\View\Resolver\ResolverInterface $resolver)
{
$this->resolver = $resolver;
}
YamlModel.php
protected $captureTo = null;
protected $terminate = true;
public function serialize()
{
/*Serialize Object and return a string*/
}
thanks
I think this is due to the order that the strategies/listeners are triggered; As once a ViewRender is found the event propagation is halted and that renderer is returned.
It seems that the standard PhpRenderStrategy has a default event priority of 1 and the others (JsonStrategy etc) seem to fire prior to this (with an even priority of 100)
Try changing the $priority; perhaps 101
$this->listeners[] = $events->attach(
ViewEvent::EVENT_RENDERER,
[$this, "selectRenderer"],
101 // <-- change here
);
I have finally found the issue.
ViewYamlStrategy.php
/* This should return a renderer */
public function selectRenderer(ViewEvent $e)
{
// here I was checking the Renderer which was not created yet
// and instead I should've checked the model
$model = $e->getModel();
if (!$model instanceof YamlModel) {
return;
}
return $this->renderer;
}