Agosto 7th 2007 02:58 am
Zend Framework - Não estenda. Plugue!
Estudo do caso
Agora que já conhecemos melhor como o Zend Framework permite a criação de plugins, supor a seguinte situação.
Seu sistema requer que TODOS os utilizadores estejam autenticados para o seu uso correto. Em outras palavras, você não pode deixar que nenhum usuário acesse suas actions sem estar autenticado no sistema (com exceção ao controller de login, óbvio!).
Poderiamos resolver o problema de três formas:
Primeira:
Em todas as action de seu sistema adicionar lógica para verificar se o usuário está autenticado ou não, caso não estiver, o usuário é redirecionado para o controller de login. O problema disso é que desta forma seria necessário utilizar do Pattern RCP (Reuse by Copy-and-Paste), o qual, não é aconselhado ao desenvolvimento de software, pois sua manutenção pode causar algumas madrugadas em claro e dores de cabeça.
Segunda:
Estender a classe Zend_Controller_Action, criando um tipo de MyCustomizedControllerAction, onde poderiamos colocar a lógica de verificação de autenticação no método MyCustomizedControllerAction::init(), então todos seus controllers estenderiam este, assim abstraindo a lógica de autenticação. Não vou discutir este tipo de solução, pois de fato não me parece tão ruim, o problema é que com isso você "amarraria" os controllers de sua aplicação ao MyCustomizedControllerAction.
Terceira:
Criar um plugin onde possa ser feita a verificação da autenticação, que caso não ocorra com sucesso, redireciona o usuário para o controller de login. Neste caso seu controle de autenticação pode ser implementado de uma maneira muito mais elegante, tendo a flexibilidade de tirar e botar esta lógica apenas alterando quatro ou cinco linhas de código.
Criando nosso plugin de verificação de autenticação
-
<?php
-
-
class SecurityPlugin extends Zend_Controller_Plugin_Abstract
-
{
-
/**
-
* verifica se o usuário esta autenticado, caso
-
* não esteja redireciona para o controller de login
-
*
-
* @param Zend_Controller_Request_Abstract $request
-
*/
-
public function routeShutdown(Zend_Controller_Request_Abstract $oRequest) {
-
$sControllerName = $oRequest->getControllerName();
-
$sActionName = $oRequest->getActionName();
-
$oAuth = Zend_Auth::getInstance();
-
-
if (strtolower($sControllerName) != 'login' && !$oAuth->hasIdentity()) {
-
$oFrontController = Zend_Controller_Front::getInstance();
-
$sBaseUrl = $oFrontController->getBaseUrl();
-
$sRedirect = urlencode($sControllerName.'/'.$sActionName);
-
$this->getResponse()->setRedirect($sBaseUrl .
-
'/login/index?redirect='.$sRedirect, 302);
-
}
-
}
-
}
Este é nosso plugin, apenas utilizei o método Zend_Controller_Plugin_Abstract::routeShutdown() para incluir a verificação de autenticação, utilizando o módulo Zend_Auth do Zend Framework para fazer a verificação.
-
if (strtolower($sControllerName) != 'login' && !$oAuth->hasIdentity()) {
caso o usuário não esteja autenticado !$oAuth->hasIdentity() e se o controller setado no request seja diferente do de login, redireciona o usuário para url de login.
-
$this->getResponse()->setRedirect($sBaseUrl .
-
'/login/index?redirect='.$sRedirect, 302);
o segundo parametro do método setRedirect() (a constante 302) é o código padrão de redirecionamentos do protocolo HTTP/1.1 definido pela RFC 2616.
13 Comments »












(2 votos, média: 4 de 5)

felipe tonello on 10 Ago 2007 at 19:03 #
achei bem legal essa abordagem de plugin..
eu sabia que podia fazer e tals mas nunca cheguei a utilizar mesmo..
Uma dúvida que tive, foi pq você usou o routeShutdown() ao invez do preDispatch() por exemplo?
Porque você precisa do route né? para saber qual é o controller usado para ver se não está usando o controller login?!
Intendi, mas sei lá, não fica 100% seguro dessa maneira… porque por exemplo o Zend_Controller_Action::__construct() é rodado, juntamente com os inits() e etc.. aí alguma informação pode ser usada sem necessiade..
A solução seria você utilizar os inits() e etc de acordo a sua lógica de plugin.
Parabéns!
diegotremper on 11 Ago 2007 at 04:55 #
Exato, você esta certo, também pensei nisso quando utilizei, mas ainda sim, gosto da idéia de utlizar os plugins para fazer o trabalho que sugeri de segurança, basta tomar alguns cuidados. Cheguei a progurar algo na lista de MVC do Zend para ver se ninguem tinha pensado algo parecido, mas não encontrei, acho que vou postar lá essa situação e ver o que o pessoal acha.
Valeu.
felipe tonello on 11 Ago 2007 at 16:20 #
Eu vi um modo de segurança igual a esse, com plugins mesmo, mas só que usando Acl.
Lá no devzone da zend mesmo, só que está em versão do ZF atrasada. Eu estou fazendo um aqui versão atualizada e usando para testes também..
Até mais diego,
Felipe
Aziz on 13 Out 2007 at 10:53 #
eu usei esse esquema de plugin em um sistema que estou desenvolvendo para renderizar cabeçalho e rodapé das paginas, mas acabei desfazendo o plugin pq não consegui fazer o titulo ficar customizado para cada pagina, a solução que arrangei foi extender a classe Zend_Controller_Action sobrescrevendo o metodo render().
fazendo algo assim:
public function render($action = null, $name = null, $noController = false)
{
#renderiza topo
$this->getResponse()->prepend(’topo’, $this->view->render(’topo.phtml’));
parent::render($action,$name,$noController);
#renderiza o rodape
$this->getResponse()->append(’rodape’, $this->view->render(’rodape.phtml’));
}
ta funfando blz, mas gostaria de saber se vc tem alguma ideia melhor?
Falow
Diego Tremper on 15 Out 2007 at 00:02 #
hum…
uma forma de fazer o que você fez é colocar dentro de cada view sua o seguinte código:
< ?php echo $this->render(’topo.phtml’); ?>
….
< ?php echo $this->render(’rodape.phtml’); ?>
[]’s
lamonato on 15 Nov 2007 at 16:20 #
Acabei fazendo como o diego, colocando dentro das views.
Parabéns pelo blog
Leonildo on 28 Abr 2008 at 16:15 #
Qual o diretório mais indicado para se colocar os plugins ?
Bruno on 14 Jul 2008 at 16:44 #
Ótimo, agradeço muito ao Diego, Felipe e Flavio Gomes por serem pioneiros aq no Brasil com esse Know-how sobre ZendFramework…me ajudaram muito….valeu mesmo…logo, logo quem sabe eu tambm naum ajude o pessoal!
links for 2008-08-02 [delicious.com] « sySolution on 02 Ago 2008 at 13:00 #
[…] Blog do Tremper » Zend Framework - Não estenda. Plugue! (tags: zend) […]
Blog do Tremper » Injeção de dependência com Zend Framework on 29 Nov 2008 at 03:50 #
[…] Porém, existem maneiras mais fáceis (e mais elegantes) de fazer isso. Injeção de Dependência é uma delas. Com o Zend Framework existem alguns pontos onde podemos aplicar este tipo de abordagem, utilizando Action Helpers, View Helpers e Plugins. Já expliquei aqui no blog como utilizar plugins, no post Não estenda. Plugue!. […]
Luiz on 23 Jan 2009 at 14:53 #
Olá,
Parabéns pelo blog, você já me ajudou e ensinou muita coisa com suas publicações.. obrigado mesmo…
Olha só ,lí seu tópico umas 50 vezes, mas não estou conseguindo adaptar para meu problema, e gostaria de uma ajudinha se possível…
Meu problema:
Estou iniciando no Zend e estou montando um menu dinâmico, ou seja, o usuário escolhe o módulo que deseja trabalhar e o Zend acessa o banco de dados e restagada somente os menus referente ao módúlo escolhido… até aí tudo em ordem…
Meu problema é que tenho um controller chamado MenuController.php e ModuloController.php, sendo que respectivamente o Menu acessa a tabela Menu e o Modulo a tabela de módulos disponíveis (exemplo: Compras, Viagens, Requisição de Compras…etc)
A idéia é que quando o usuário acessar uma página (qualquer controller) o Zend faça uma espécie de require_once no controller chamado “montamenu” para que se crie o menu com as opções…..
Tentei quase de tudo, require_once, render, include, _forward, _redirect… e nada funcionou, tirando o _forward que deu certo mas não ficou uma programação dinâmica…. e sim muito manual…
Quando de muita pesquisa acabei batendo neste post que achei que seria minha solução, mas não estou conseguindo criar meu plugin para apenas carregar e montar o menu do banco de dados..
Para usar o plugin no zend tenho que registar ele no sistema, o registro se faz no bootstrap ? o plugin deve ser salvo dentro da pasta Controller ?
Segui se exemplo mas ele dá Class not Found… (hehehehe)
Terias por acaso um exemplo voltado para menus ?
Obrigado pela ajuda,
Luiz
Arian Maykon (Dead_Thinker) on 07 Fev 2009 at 20:46 #
@Aziz - Cara, acho que se tu estudar e usar o Zend_Layout resolve teu problema de uma forma mais elegante. Dá uma olhada.
@Luiz - acho que pro teu caso mano seria melhor um View_Helper não? E nele tu poderia pegar dados da requisição/sessão e montar o menu conforme desejado. Dá uma sakada, uso um View_Helper pra renderizar os menus.
Thiago Colares on 09 Out 2009 at 12:14 #
Muito bom o post, parabéns pelo blog