Commit cbed5367285694954990d5903812bbd79bf27192

Authored by Dancovich
1 parent 6b429231
Exists in master

Escrita documentação atualizada de segurança

Showing 1 changed file with 501 additions and 123 deletions   Show diff stats
documentation/reference/pt-BR/security.xml
1 <?xml version='1.0' encoding="utf-8"?> 1 <?xml version='1.0' encoding="utf-8"?>
2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" 2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3 - "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []> 3 + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ ]>
4 <chapter id="security"> 4 <chapter id="security">
5 5
6 <title>Segurança</title> 6 <title>Segurança</title>
@@ -9,19 +9,21 @@ @@ -9,19 +9,21 @@
9 Neste capítulo será tratada uma questão de grande importância para a maioria das aplicações e motivo de infindáveis 9 Neste capítulo será tratada uma questão de grande importância para a maioria das aplicações e motivo de infindáveis
10 discussões nas equipes de desenvolvimento: controle de acesso. Assim como tudo relacionado ao framework, a 10 discussões nas equipes de desenvolvimento: controle de acesso. Assim como tudo relacionado ao framework, a
11 implementação de segurança foi projetada de forma simples e flexível, independente de camada de apresentação ou 11 implementação de segurança foi projetada de forma simples e flexível, independente de camada de apresentação ou
12 - tecnologia, te deixando livre para implementar sua própria solução ou utilizar as extensões prontas, como a que  
13 - atualmente provemos baseada no Apache Shiro (<ulink url="http://shiro.apache.org" />). 12 + tecnologia, te deixando livre para implementar sua própria solução ou utilizar as extensões existentes.
14 </para> 13 </para>
15 <para> 14 <para>
16 - Para utilizar o modelo de segurança proposto basta utilizar o Demoiselle, pois no núcleo do Framework estão as 15 + Para utilizar o modelo de segurança proposto basta utilizar o Framework Demoiselle, pois no núcleo do framework estão as
17 interfaces e anotações que definem o comportamento básico da implementação. 16 interfaces e anotações que definem o comportamento básico da implementação.
18 </para> 17 </para>
19 18
20 <section> 19 <section>
21 <title>Configurando</title> 20 <title>Configurando</title>
  21 +
22 <para> 22 <para>
23 - Para um correto funcionamento do Demoiselle é necessário inserir os interceptadores de segurança no arquivo <filename>src/main/WEB-INF/beans.xml</filename>. 23 + Para um correto funcionamento da segurança no Framework Demoiselle é necessário inserir os interceptadores de segurança no arquivo <filename>beans.xml</filename>, localizado
  24 + na pasta WEB-INF em projetos WEB ou na pasta META-INF em projetos SE ou EJB.
24 </para> 25 </para>
  26 +
25 <programlisting role="XML"><![CDATA[<beans xmlns="http://java.sun.com/xml/ns/javaee" 27 <programlisting role="XML"><![CDATA[<beans xmlns="http://java.sun.com/xml/ns/javaee"
26 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 28 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
27 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 29 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
@@ -31,208 +33,584 @@ xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee @@ -31,208 +33,584 @@ xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee
31 <class>br.gov.frameworkdemoiselle.security.RequiredRoleInterceptor</class> 33 <class>br.gov.frameworkdemoiselle.security.RequiredRoleInterceptor</class>
32 </interceptors> 34 </interceptors>
33 </beans>]]></programlisting> 35 </beans>]]></programlisting>
  36 +
  37 + <para>
  38 + Opcionalmente é possível configurar o comportamento do módulo de segurança definindo propriedades no arquivo <emphasis>demoiselle.properties</emphasis>
  39 + da sua aplicação.
  40 + </para>
  41 +
  42 + <table>
  43 + <title>Propriedades de segurança do Framework Demoiselle</title>
  44 + <tgroup cols="3">
  45 + <colspec align="left"/>
  46 + <colspec align="left"/>
  47 + <colspec align="right"/>
  48 +
  49 + <thead>
  50 + <row valign="top">
  51 + <entry><emphasis role="bold">Propriedade</emphasis></entry>
  52 + <entry><emphasis role="bold">Descrição</emphasis></entry>
  53 + <entry><emphasis role="bold">Valor padrão</emphasis></entry>
  54 + </row>
  55 + </thead>
  56 + <tbody>
  57 + <row valign="top">
  58 + <entry>frameworkdemoiselle.security.enabled</entry>
  59 + <entry>
  60 + <para>
  61 + Habilita ou desabilita o mecanismo de segurança
  62 + </para>
  63 + </entry>
  64 + <entry>true</entry>
  65 + </row>
  66 +
  67 + <row valign="top">
  68 + <entry>frameworkdemoiselle.security.authenticator.class</entry>
  69 + <entry>
  70 + <para>
  71 + Define a classe que implementa o mecanismo de autenticação.
  72 + (Detalhes na seção <link linkend="criando_implementacao_seguranca">Criando sua implementação</link>)
  73 + </para>
  74 + </entry>
  75 + <entry>
  76 + -
  77 + </entry>
  78 + </row>
  79 +
  80 + <row valign="top">
  81 + <entry>frameworkdemoiselle.security.authorizer.class</entry>
  82 + <entry>
  83 + <para>
  84 + Define a classe que implementa o mecanismo de autorização.
  85 + (Detalhes na seção <link linkend="criando_implementacao_seguranca">Criando sua implementação</link>)
  86 + </para>
  87 + </entry>
  88 + <entry>
  89 + -
  90 + </entry>
  91 + </row>
  92 + </tbody>
  93 + </tgroup>
  94 + </table>
  95 +
34 </section> 96 </section>
35 97
36 <section> 98 <section>
37 <title>Autenticação</title> 99 <title>Autenticação</title>
38 <para> 100 <para>
39 - O mecanismo de autenticação busca verificar a identidade do usuário de um sistema. A forma mais conhecida, e comum,  
40 - para executar essa verificação se dá por meio de um formulário de login, geralmente solicitando um nome de usuário e 101 + O mecanismo de autenticação busca verificar a identidade do usuário de um sistema. A forma mais conhecida - e comum - para
  102 + executar essa verificação se dá por meio de um formulário de login, geralmente solicitando um nome de usuário e
41 sua respectiva senha. No entanto, outras formas como reconhecimento biométrico e autenticação por token, para citar 103 sua respectiva senha. No entanto, outras formas como reconhecimento biométrico e autenticação por token, para citar
42 - apenas duas, têm ganhado um grande número de adeptos. 104 + apenas duas, tem ganhado um grande número de adeptos.
43 </para> 105 </para>
44 <para> 106 <para>
45 - O Demoiselle deixa o desenvolvedor livre para definir qual forma usar, de acordo com a sua conveniência e necessidade.  
46 - A peça chave para tornar isso possível é o contexto de segurança, representado pela interface SecurityContext. Nessa 107 + O Framework Demoiselle deixa o desenvolvedor livre para definir qual forma usar, de acordo com a sua conveniência e necessidade.
  108 + A peça chave para tornar isso possível é o contexto de segurança, representado pela interface <code>SecurityContext</code>. Nessa
47 estão definidos os métodos responsáveis por gerenciar os mecanismos de autenticação como, por exemplo, executar 109 estão definidos os métodos responsáveis por gerenciar os mecanismos de autenticação como, por exemplo, executar
48 login/logout de usuários e verificar se os mesmos estão ou não autenticados. 110 login/logout de usuários e verificar se os mesmos estão ou não autenticados.
49 </para> 111 </para>
50 <para> 112 <para>
51 - O contexto de segurança irá direcionar as requisições para a implementação definida pela aplicação. A autenticação será  
52 - efetuada por uma classe que implemente a interface Authenticator, cujo método authenticate() é responsável por  
53 - executar os passos necessários para validar a identidade de um usuário. Nesta mesma interface serão encontrados,  
54 - ainda, os métodos unAuthenticate() e getUser(), responsáveis por, respectivamente, desautenticar e retornar o usuário  
55 - autenticado.  
56 - </para>  
57 - <para>  
58 - Para exemplificar, consideremos a autenticação baseada em nome de usuário e senha. O primeiro passo é criar um bean para  
59 - armazenar essas informações: 113 + Para utilizar o <code>SecurityContext</code>, basta injetá-lo em seu código. O método <code>login</code> ativa o mecanismo de autenticação
  114 + e o método <code>logout</code> remove as credenciais atualmente autenticadas do sistema. A classe <code>SecurityContext</code> possui
  115 + outros métodos que permitem verificar se há um usuário autenticado e acessar o objeto <emphasis>gerente</emphasis> (representado pela
  116 + classe <code>javax.security.Principal</code>), um objeto que contém dados adicionais sobre o usuário atualmente autenticado. Consulte
  117 + a documentação da classe <code>SecurityContext</code> para consultar as funcionalidades que ela oferece.
60 </para> 118 </para>
61 - <programlisting role="JAVA"><![CDATA[@SessionScoped  
62 -public class Credential {  
63 -  
64 - private String login;  
65 - private String senha;  
66 - // ...  
67 -}]]></programlisting>  
68 <para> 119 <para>
69 - Feito isso, podemos implementar a classe na qual se deseja adicionar o mecanismo de segurança: 120 + Um exemplo do uso do <code>SecurityContext</code> para autenticação segue abaixo:
70 </para> 121 </para>
71 - <programlisting role="JAVA"><![CDATA[public class ClasseExemplo {  
72 -  
73 - @Inject  
74 - private Credential credential; 122 + <programlisting role="JAVA"><![CDATA[public class ExemploAutenticacao {
75 123
76 @Inject 124 @Inject
77 - private SecurityContext context;  
78 -  
79 - public void metodo1() {  
80 - credential.setLogin(“usuario1”);  
81 - credential.setSenha(“123”);  
82 - context.login();  
83 - // codigo do metodo  
84 - context.logout(); 125 + private SecurityContext securityContext;
  126 +
  127 + public void efetuarAutenticacao() {
  128 + /*
  129 + Obtém as credenciais do usuário, pode ser um login e senha ou um certificado digital. O mais
  130 + comum é exibir uma tela HTML contendo um formulário que solicita as informações.
  131 + */
  132 +
  133 + securityContext.login();
  134 +
  135 + //Executa código que requer autenticação
  136 +
  137 + securityContext.logout();
  138 +
85 } 139 }
86 }]]></programlisting> 140 }]]></programlisting>
87 - <para>  
88 - Neste caso, a interface SecurityContext e o bean Credential estão sendo injetados na classe utilizando o CDI.  
89 - Dentro do método, ao definir o usuário e a senha e invocar “context.login()”, a implementação de segurança definida irá  
90 - tratar essa requisição de acordo com os critérios estabelecidos.  
91 - </para>  
92 </section> 141 </section>
93 142
94 <section> 143 <section>
95 <title>Autorização</title> 144 <title>Autorização</title>
96 <para> 145 <para>
97 - O mecanismo de autorização é responsável por garantir que apenas usuários autorizados tenham o acesso concedido a  
98 - determinados recursos de um sistema. No modelo de segurança do Demoiselle 2, a autorização pode acontecer de duas 146 + Em certos sistemas é necessário não apenas autenticar um usuário, mas também proteger funcionalidades individuais e separar
  147 + usuários em grupos que possuem diferentes autorizações de acesso. O mecanismo de autorização é responsável por garantir que apenas
  148 + usuários autorizados tenham o acesso concedido a determinados recursos de um sistema.
  149 + </para>
  150 +
  151 + <para>
  152 + No modelo de segurança do Framework Demoiselle, a autorização pode acontecer de duas
99 formas: 153 formas:
100 <itemizedlist> 154 <itemizedlist>
101 - <listitem><para>Permissão por usuário, através da anotação @RequiredPermission</para></listitem> 155 + <listitem><para>Permissão por funcionalidade, através da anotação @RequiredPermission</para></listitem>
102 <listitem><para>Permissão por papel, através da anotação @RequiredRole</para></listitem> 156 <listitem><para>Permissão por papel, através da anotação @RequiredRole</para></listitem>
103 </itemizedlist> 157 </itemizedlist>
104 </para> 158 </para>
105 - <para>  
106 - Novamente a interface SecurityContext é a responsável pela interação entre as funcionalidades da aplicação e a implementação de  
107 - segurança. Nela estão definidos os métodos que verificam se o usuário possui permissão para acessar um recurso ou se o  
108 - usuário está associado a um papel.  
109 - </para>  
110 - <para>  
111 - A anotação @RequiredPermission pode ser utilizada tanto em classes como em métodos e possui dois parâmetros opcionais:  
112 - “operation” e “resource”. O primeiro define a operação para a qual se deseja permissão e o segundo define em qual  
113 - recurso essa operação será realizada. Abaixo serão exemplificadas algumas formas de utilização:  
114 - </para>  
115 - <programlisting role="JAVA"><![CDATA[class ClasseExemplo { 159 +
  160 +
  161 + <section>
  162 + <title>Protegendo o sistema com <emphasis>@RequiredPermission</emphasis></title>
  163 +
  164 + <para>
  165 + A anotação <code>@RequiredPermission</code> permite marcar uma classe ou método e informar que acesso a esse recurso requer
  166 + a permissão de executar uma <emphasis>operação</emphasis>. Operação nesse contexto é um nome definido pelo desenvolvedor
  167 + que representa uma funcionalidade do sistema. Por exemplo, determinada classe pode ter métodos responsávels por criar, editar,
  168 + listar e remover bookmarks, o desenvolvedor pode decidir agrupar esses métodos sobre a operação <emphasis>gerenciar bookmark</emphasis>.
  169 + </para>
  170 +
  171 + <programlisting role="JAVA"><![CDATA[class GerenciadorBookmark {
116 172
117 - @RequiredPermission  
118 - public void requiredPermissionWithoutDeclaredResourceAndOperation() { 173 + @RequiredPermission(resource = "bookmark" , operation = "gerenciar")
  174 + public void incluirBookmark(Bookmark bookmark) {
  175 + //Código do método
119 } 176 }
120 177
121 - @RequiredPermission(resource = "contact", operation = "insert")  
122 - public void requiredPermissionWithDeclaredResourceAndOperation() {  
123 - } 178 + @RequiredPermission(resource = "bookmark", operation = "gerenciar")
  179 + public List<Bookmark> listarBookmarks() {
  180 + //Código do método
  181 + }
  182 +
  183 + @RequiredPermission
  184 + public List<Bookmark> apagarBookmark(Long idBookmark) {
  185 + public List<Bookmark> listarBookmarks() {
  186 + }
124 }]]></programlisting> 187 }]]></programlisting>
  188 +
  189 + <tip>
  190 + Perceba que a anotação <code>@RequiredPermission</code> sobre o método <code>apagarBookmark</code> não contém parâmetros. Quando não
  191 + são passados parâmetros o valor padrão para o parâmetro <code>resource</code> é o nome da classe e o valor padrão para <code>operation</code>
  192 + é o nome do método.
  193 + </tip>
  194 +
  195 + <tip>
  196 + É possível anotar a classe inteira com <code>@RequiredPermission</code>, isso protegerá o acesso a todos os métodos dessa classe.
  197 +
  198 + <programlisting role="JAVA"><![CDATA[@RequiredPermission(resource="bookmark" , operation="gerenciar")
  199 +class GerenciadorBookmark {
  200 +
  201 + public void incluirBookmark(Bookmark bookmark) {
  202 + //Código do método
  203 + }
  204 +
  205 + public List<Bookmark> listarBookmarks() {
  206 + //Código do método
  207 + }
  208 +
  209 + public List<Bookmark> apagarBookmark(Long idBookmark) {
  210 + public List<Bookmark> listarBookmarks() {
  211 + }
  212 +}]]></programlisting>
  213 + </tip>
  214 + </section>
  215 +
  216 + <section>
  217 + <title>Protegendo o sistema com <emphasis>@RequiredRole</emphasis></title>
  218 +
  219 + <para>
  220 + Diferente de <code>@RequiredPermission</code>, a anotação <code>@RequiredRole</code> utiliza o conceito
  221 + de papéis - ou perfís - para proteger recursos. Uma classe ou método anotado com <code>@RequiredRole</code>
  222 + exigirá que o usuário autenticado possua o papel indicado para acessar o recurso.
  223 + </para>
  224 +
  225 + <para>
  226 + Voltando ao exemplo de nosso aplicativo de bookmarks, vamos supor que a função de listar os bookmarks existentes
  227 + pode ser acessada por qualquer usuário autenticado, mas apenas administradores podem criar um novo bookmark. A classe
  228 + responsável por tais funcionalidades pode ser criada da seguinte forma:
  229 + </para>
  230 +
  231 + <programlisting role="JAVA"><![CDATA[class GerenciadorBookmark {
  232 +
  233 + @RequiredRole("administrador")
  234 + public void inserirBookmark(Bookmark bookmark) {
  235 + }
  236 +
  237 + @RequiredRole({"convidado" , "administrador"})
  238 + public List<Bookmark> listarBookmarks() {
  239 + }
  240 +
  241 +}]]></programlisting>
  242 +
  243 + <tip>
  244 + É possível informar mais de um papel para a anotação <code>@RequiredRole</code>, neste caso basta que o usuário
  245 + autenticado possua um dos papéis listados para ter acesso ao recurso.
  246 + </tip>
  247 +
  248 + <para>
  249 + Da mesma forma que a anotação <code>@RequiredPermission</code>, a anotação <code>@RequiredRole</code> pode ser usada
  250 + a nível de classe para proteger todos os métodos contidos nessa classe.
  251 + </para>
  252 + </section>
  253 +
  254 + <section>
  255 + <title>Protegendo porções do código</title>
  256 +
  257 + <para>
  258 + É possível proteger apenas parte de um código ao invés de todo o método ou toda a classe. Isso pode ser necessário em
  259 + expressões condicionais, onde um trecho só deve ser executado caso o usuário possua a autorização necessária.
  260 + Para isso voltamos a usar a interface <code>SecurityContext</code>, pois ela contém métodos que são funcionalmente equivalentes
  261 + às anotações <code>@RequiredPermission</code> e <code>@RequiredRole</code>.
  262 + </para>
  263 +
  264 + <para>
  265 + Como um exemplo, vamos supor que ao remover um bookmark um email seja enviado ao administrador, mas se o próprio
  266 + administrador executou a operação não é necessário enviar o email.
  267 + </para>
  268 +
  269 + <programlisting role="JAVA"><![CDATA[class GerenciadorBookmark {
  270 +
  271 + @Inject
  272 + private SecurityContext securityContext;
  273 +
  274 + public void removerBookmark(Long idBookmark) {
  275 +
  276 + //Código que remove o bookmark
  277 +
  278 + if ( ! securityContext.hasRole("administrador") ){
  279 + //Envia um email ao administrador
  280 + }
  281 +
  282 + }
  283 +
  284 +}]]></programlisting>
  285 +
  286 + </section>
  287 +
  288 + <section>
  289 + <title>Protegendo porções de páginas <code>Java Server Faces</code></title>
  290 +
  291 + <para>
  292 + As restrições de segurança podem ser utilizadas ainda em páginas web, com o auxílio de Expression Language. A interface
  293 + <code>SecurityContext</code> está automaticamente disponível para páginas <code>Java Server Faces</code> como um <emphasis>bean</emphasis>
  294 + de nome <code>securityContext</code>, bastando então acessar seus métodos a partir deste bean.
  295 + </para>
  296 +
  297 + <programlisting role="XHTML"><![CDATA[<p:commandButton value="#{messages['button.save']}" action="#{contactEditMB.insert}"
  298 + ajax="false" disabled="#{!securityContext.hasPermission('contact', 'insert')}" />]]></programlisting>
  299 +
  300 + <para>
  301 + Nesse caso, a habilitação de um botão está condicionada à existência de permissão para o usuário autenticado no momento
  302 + executar a operação “insert” no recurso “contact”.
  303 + </para>
  304 + </section>
  305 + </section>
  306 +
  307 + <section>
  308 + <title>Redirecionando automaticamente para um formulário de acesso</title>
  309 +
  310 + <para>
  311 + Se sua aplicação usa a extensão <emphasis>demoiselle-jsf</emphasis> ou se você utilizou o arquétipo <emphasis>demoiselle-jsf-jpa</emphasis>
  312 + durante a criação de seu projeto, então você pode definir uma página de login e o Framework Demoiselle vai automaticamente lhe redirecionar
  313 + para essa página caso haja a tentativa de acessar um recurso protejido e nenhum usuário esteja autenticado no sistema.
  314 + </para>
  315 +
  316 + <tip>
  317 + <para>Para acrescentar a extensão <emphasis>demoiselle-jsf</emphasis> em um projeto Maven, adicione a dependência abaixo
  318 + no arquivo <emphasis>pom.xml</emphasis>.</para>
  319 +
  320 + <programlisting role="XML"><![CDATA[
  321 +<dependency>
  322 + <groupId>br.gov.frameworkdemoiselle</groupId>
  323 + <artifactId>demoiselle-jsf</artifactId>
  324 + <scope>compile</scope>
  325 +</dependency>]]></programlisting>
  326 +
  327 + <para>
  328 + O arquétipo <emphasis>demoiselle-jsf-jpa</emphasis> já contém essa extensão, se você criou seu projeto
  329 + baseado nesse arquétipo nada precisa ser feito.
  330 + </para>
  331 + </tip>
  332 +
125 <para> 333 <para>
126 - Observe o método cuja anotação não possui parâmetros. Nesse caso serão considerados como recurso e operação o nome da classe e  
127 - do método, respectivamente. Uma outra possibilidade seria utilizar a anotação @Name, tanto na classe como no método, de  
128 - forma a possibilitar uma descrição mais amigável para o usuário. 334 + Por padrão a página contendo o formulário de login deve se chamar <emphasis>login.jsp</emphasis> ou <emphasis>login.xhtml</emphasis>
  335 + (a depender de como sua aplicação esteja configurada para mapear páginas JSF). Para mudar esse padrão, é possível
  336 + editar o arquivo <emphasis>demoiselle.properties</emphasis> para configurar qual página deve ser utilizada.
129 </para> 337 </para>
  338 +
  339 + <table>
  340 + <title>Propriedades de segurança da extensão <emphasis>demoiselle-jsf</emphasis></title>
  341 + <tgroup cols="3">
  342 + <colspec align="left"/>
  343 + <colspec align="left"/>
  344 + <colspec align="right"/>
  345 +
  346 + <thead>
  347 + <row valign="top">
  348 + <entry><emphasis role="bold">Propriedade</emphasis></entry>
  349 + <entry><emphasis role="bold">Descrição</emphasis></entry>
  350 + <entry><emphasis role="bold">Valor padrão</emphasis></entry>
  351 + </row>
  352 + </thead>
  353 + <tbody>
  354 + <row valign="top">
  355 + <entry>frameworkdemoiselle.security.login.page</entry>
  356 + <entry>
  357 + <para>
  358 + Define a página de login da aplicação.
  359 + </para>
  360 + </entry>
  361 + <entry>"/login"</entry>
  362 + </row>
  363 + <row valign="top">
  364 + <entry>frameworkdemoiselle.security.redirect.after.login</entry>
  365 + <entry>
  366 + <para>
  367 + Define a tela para qual o usuário será redirecionado após o processo de <emphasis>login</emphasis> bem sucedido.
  368 + </para>
  369 + </entry>
  370 + <entry>"/index"</entry>
  371 + </row>
  372 + <row valign="top">
  373 + <entry>frameworkdemoiselle.security.redirect.after.logout</entry>
  374 + <entry>
  375 + <para>
  376 + Define a tela para qual o usuário será redirecionado após o processo de <emphasis>logout</emphasis> bem sucedido.
  377 + </para>
  378 + </entry>
  379 + <entry>"/login"</entry>
  380 + </row>
  381 + <row valign="top">
  382 + <entry>frameworkdemoiselle.security.redirect.enabled</entry>
  383 + <entry>
  384 + <para>
  385 + Habilita ou desabilita o redirecionamento automático para a página de login após uma tentativa
  386 + de acessar recurso protegido.
  387 + </para>
  388 + </entry>
  389 + <entry>true</entry>
  390 + </row>
  391 + </tbody>
  392 + </tgroup>
  393 + </table>
  394 +
  395 + </section>
  396 +
  397 + <section>
  398 + <title>Integrando o Framework Demoiselle com a especificação JAAS</title>
  399 +
130 <para> 400 <para>
131 - Assim como na autenticação, o contexto de segurança possui métodos destinados a delegar as requisições de autorização para  
132 - a implementação de segurança. No caso da anotação @RequiredPermission, o método hasPermission(String resource, String  
133 - operation) executa esta tarefa. Para tanto, deve existir uma classe que implemente a interface Authorizer, cujo  
134 - método hasPermission(Object resource, String operation) verifica se o usuário logado possui permissão para executar  
135 - uma determinada operação em um recurso específico. 401 + Até agora vimos como criar código protegido em uma aplicação Demoiselle, mas nada foi dito sobre a tecnologia que implementa essa
  402 + proteção. A verdade é que o Framework Demoiselle dá ao desenvolvedor a liberdade de implementar a solução que mais se adequa ao sistema
  403 + desenvolvido, mas o framework também conta com suporte nativo à especificação JAAS (<emphasis>Java Authentication and
  404 + Authorization Service</emphasis>).
136 </para> 405 </para>
  406 +
137 <para> 407 <para>
138 - Ainda na interface Authorizer, pode-se notar a existência do método hasRole(String role), responsável por verificar se o  
139 - usuário logado possui um papel específico. Este método é chamado pelo contexto de segurança, por meio do seu método  
140 - hasRole(String role), para tratar as requisições que possuam a anotação @RequiredRole. Essa anotação possui um  
141 - parâmetro obrigatório, no qual podem ser definidos uma simples role ou um array delas. 408 + O suporte a JAAS é fornecido para aplicações WEB e está implementado na extensão
  409 + <emphasis>demoiselle-servlet</emphasis>, então é necessário declarar a dependência a essa extensão em sua aplicação.
142 </para> 410 </para>
143 - <programlisting role="JAVA"><![CDATA[class ClasseExemplo { 411 +
  412 + <tip>
  413 + <para>Para acrescentar a extensão <emphasis>demoiselle-servlet</emphasis> em um projeto Maven, adicione a dependência abaixo
  414 + no arquivo <emphasis>pom.xml</emphasis>.</para>
  415 +
  416 + <programlisting role="XML"><![CDATA[
  417 +<dependency>
  418 + <groupId>br.gov.frameworkdemoiselle</groupId>
  419 + <artifactId>demoiselle-servlet</artifactId>
  420 + <scope>compile</scope>
  421 +</dependency>]]></programlisting>
  422 + </tip>
  423 +
  424 + <tip>
  425 + <para>
  426 + O arquétipo <emphasis>demoiselle-jsf-jpa</emphasis> já conta com a dependência à extensão <emphasis>demoiselle-jsf</emphasis>, que
  427 + por sua vez depende da extensão <emphasis>demoiselle-servlet</emphasis>. Se sua aplicação é baseada no arquétipo
  428 + <emphasis>demoiselle-jsf-jpa</emphasis> você já possui a extensão <emphasis>demoiselle-servlet</emphasis>.
  429 + </para>
  430 + </tip>
  431 +
  432 + <para>
  433 + Uma vez que sua aplicação contenha a extensão <emphasis>demoiselle-servlet</emphasis>, tudo que você precisa fazer é configurar
  434 + o suporte a JAAS em seu servidor de aplicação e criar os usuários e papéis necessários. Esta configuração depende do servidor de
  435 + aplicação utilizado e foge ao escopo deste documento.
  436 + </para>
  437 +
  438 + <para>
  439 + Para autenticar um usuário presente no servidor de aplicação através do JAAS, a extensão <emphasis>demoiselle-servlet</emphasis>
  440 + oferece a classe <code>Credentials</code>, que deve ser injetada em seu código. O código abaixo mostra como realizar a autenticação a partir de um servlet.
  441 + </para>
  442 +
  443 + <programlisting role="JAVA"><![CDATA[class LoginServlet extends HttpServlet {
  444 +
  445 + @Inject
  446 + private SecurityContext securityContext;
  447 +
  448 + @Inject
  449 + private Credentials credentials;
144 450
145 - @RequiredRole("simpleRoleName")  
146 - public void requiredRoleWithSingleRole() { 451 + public void doPost(HttpServletRequest req, HttpServletResponse resp) {
  452 +
  453 + credentials.setUsername( req.getParameter("username") );
  454 + credentials.setPassword( req.getParameter("password") );
  455 +
  456 + securityContext.login();
  457 +
147 } 458 }
148 459
149 - @RequiredRole({ "firstRole", "secondRole", "thirdRole", "fourthRole", "fifthRole" })  
150 - public void requiredRoleWithArrayOfRoles() {  
151 - }  
152 }]]></programlisting> 460 }]]></programlisting>
  461 +
153 <para> 462 <para>
154 - As restrições de segurança pode ser utilizadas, ainda, em páginas web, com o auxílio de Expression Language, como no  
155 - exemplo abaixo:  
156 - </para>  
157 - <programlisting role="XHTML"><![CDATA[<p:commandButton value="#{messages['button.save']}" action="#{contactEditMB.insert}"  
158 - rendered="#{!contactEditMB.updateMode}" ajax="false"  
159 - disabled="#{!securityContext.hasPermission('contact', 'insert')}" />]]></programlisting>  
160 - <para>  
161 - Nesse caso, a habilitação de um botão está condicionada à existência de permissão para o usuário autenticado no momento  
162 - executar a operação “insert” no recurso “contact”. 463 + Uma vez autenticado o usuário, a anotação <code>@RequiredRole</code> passará a verificar se o usuário presente no JAAS possui o papel informado.
163 </para> 464 </para>
  465 +
  466 + <caution>
  467 + <para>
  468 + A especificação JAAS não prevê o uso de permissões para proteger recursos, apenas papéis de usuários. Por isso ao utilizar a segurança
  469 + da especificação JAAS o uso da anotação <code>@RequiredPermission</code> fica vetado. Utilizar essa anotação em um sistema que utilize
  470 + JAAS para autorização causará uma exceção quando o recurso for acessado.
  471 + </para>
  472 + </caution>
  473 +
  474 + <tip>
  475 + <para>
  476 + É possível utilizar o JAAS para autenticar e autorizar papéis de usuários mas criar sua própria implementação para
  477 + implementar a autorização de permissões. Para isso crie uma classe que herde a classe
  478 + <code>br.gov.frameworkdemoiselle.security.ServletAuthorizer</code> e sobrescreva o método <code>hasPermission(String resource, String operation)</code>
  479 + para implementar seu próprio mecanismo. Feito isso, basta definir sua classe no arquivo <emphasis>demoiselle.properties</emphasis> usando
  480 + a propriedade <code>frameworkdemoiselle.security.authorizer.class</code>.
  481 + </para>
  482 +
  483 + <para>
  484 + Mais detalhes sobre como criar sua própria implementação ou extender uma implementação existente podem
  485 + ser vistos na seção <link linkend="criando_implementacao_seguranca">Criando sua implementação</link>.
  486 + </para>
  487 + </tip>
  488 +
164 </section> 489 </section>
165 490
166 - <section> 491 + <section id="criando_implementacao_seguranca">
167 <title>Criando sua implementação</title> 492 <title>Criando sua implementação</title>
  493 +
168 <para> 494 <para>
169 - Após toda essa explicação, fica a dúvida: como implementar um esquema de segurança sem utilizar a extensão existente? 495 + Para os mecanismos de autenticação não cobertos pelo Framework Demoiselle, é possível criar sua própria implementação e integra-la
  496 + ao framework. Também é possível extender uma implementação existente e acrescentar funcionalidades inexistentes.
170 </para> 497 </para>
  498 +
171 <para> 499 <para>
172 - O primeiro passo é criar classes para implementar as interfaces Authenticator e Authorizer. O <literal>Demoiselle</literal> detecta automaticamente  
173 - a implementação, e torna essa classe a implementação padrão dessas interfaces:<!-- Essas classes devem ser  
174 - anotadas com @Alternative para que o CDI saiba que se trata de uma estratégia: --> 500 + O ponto de extensão para o módulo de segurança são as interfaces <code>Authenticator</code> e <code>Authorizer</code>. Para criar
  501 + um novo mecanismo de autenticação e autorização, é necessário apenas implementar essas duas interfaces em sua aplicação. Segue
  502 + abaixo um exemplo de implementação.
175 </para> 503 </para>
  504 +
176 <programlisting role="JAVA"><![CDATA[public class MeuAuthenticator implements Authenticator { 505 <programlisting role="JAVA"><![CDATA[public class MeuAuthenticator implements Authenticator {
177 506
178 @Override 507 @Override
179 public boolean authenticate() { 508 public boolean authenticate() {
180 - // Escreva aqui seu codigo de autenticacao 509 + // Escreva aqui seu codigo de autenticacao e retorne true caso o processo seja um sucesso
181 return true; 510 return true;
182 } 511 }
183 512
184 @Override 513 @Override
185 - public User getUser() {  
186 - // Escreva aqui seu codigo para retornar o usuario logado  
187 - return null; 514 + public Principal getUser() {
  515 + // Obtenha dados sobre o usuário autenticado e retorne na forma da interface javax.security.Principal
  516 + return new Principal(){
  517 + public String getName(){
  518 + return "usuario";
  519 + }
  520 + };
188 } 521 }
189 522
190 @Override 523 @Override
191 public void unAuthenticate() { 524 public void unAuthenticate() {
192 - // Escreva aqui seu codigo de desautenticacao 525 + // Remova qualquer informação de autenticação do usuário, após o retorno deste método o usuário
  526 + // deve ser considerado não autenticado.
193 } 527 }
194 }]]></programlisting> 528 }]]></programlisting>
195 <programlisting role="JAVA"><![CDATA[public class MeuAuthorizer implements Authorizer { 529 <programlisting role="JAVA"><![CDATA[public class MeuAuthorizer implements Authorizer {
196 530
197 @Override 531 @Override
198 public boolean hasRole(String role) { 532 public boolean hasRole(String role) {
199 - // Escreva aqui seu codigo de verificacao do papel 533 + // Verifique se o usuário autenticado tem o papel informado, retorne true em caso positivo
200 return false; 534 return false;
201 } 535 }
202 536
203 @Override 537 @Override
204 public boolean hasPermission(Object resource, String operation) { 538 public boolean hasPermission(Object resource, String operation) {
205 - // Escreva aqui seu codigo de verificacao de permissao 539 + // Verifique se o usuário autenticado tem a permissão adequada, retorne true em caso positivo
206 return false; 540 return false;
207 } 541 }
208 }]]></programlisting> 542 }]]></programlisting>
209 - <!-- <para>  
210 - Feito isso deve-se definir no arquivo <filename>demoiselle.properties</filename>, as classes criadas:  
211 - </para>  
212 - <programlisting>  
213 - frameworkdemoiselle.security.authenticator.class=projeto.MeuAuthenticator  
214 - frameworkdemoiselle.security.authorizer.class=projeto.MeuAuthorizer  
215 - </programlisting> --> 543 +
216 <para> 544 <para>
217 Pronto! Sua aplicação já possui uma implementação de segurança definida. 545 Pronto! Sua aplicação já possui uma implementação de segurança definida.
218 </para> 546 </para>
219 - 547 +
  548 + <tip>
  549 + <para>
  550 + Você nunca deve chamar diretamente em sua aplicação as implementações das interfaces <code>Authenticator</code>
  551 + e <code>Authorizer</code>, o Framework Demoiselle vai automaticamente chamar os métodos implementados
  552 + quando for necessário.
  553 + </para>
  554 + </tip>
  555 +
220 <para> 556 <para>
221 - Caso sua aplicação detecte o uso das anotações @RequiredRole e @RequiredPermission mas nenhuma classe  
222 - implemente essas interfaces, no momento em que os recursos anotados forem acessados, o framework lançará uma exceção informando que a  
223 - aplicação precisa implementá-las. 557 + Em um sistema que use as anotações <code>@RequiredRole</code> ou <code>@RequiredPermission</code>, deve haver pelo menos uma implementação
  558 + dessas duas interfaces. Ao processar essas anotações, o Framework Demoiselle vai buscar uma implementação para essas interfaces
  559 + e disparar uma exceção caso não encontre uma implementação adequada.
224 </para> 560 </para>
  561 +
225 <para> 562 <para>
226 - Se você tem mais de uma implementação de <literal>Authenticator</literal> e/ou <literal>Authorizer</literal> (o que pode acontecer, por exemplo, quando  
227 - se necessite de uma implementação na aplicação principal, e outra para os testes), deverá definir no arquivo <filename>demoiselle.properties</filename>  
228 - qual classe será a padrão:  
229 - <programlisting>frameworkdemoiselle.security.authenticator.class=projeto.MeuAuthenticatorPadrao  
230 -frameworkdemoiselle.security.authorizer.class=projeto.MeuAuthorizerPadrao</programlisting> 563 + Se existe mais de uma implementação de <code>Authenticator</code> e/ou <code>Authorizer</code> (o que pode acontecer, por exemplo, quando
  564 + seja necessário uma implementação na aplicação principal e outra para os testes), é possível definir no arquivo <filename>demoiselle.properties</filename>
  565 + a classe que deve ser usada por padrão:
231 </para> 566 </para>
  567 +
  568 + <informaltable>
  569 + <tgroup cols="3">
  570 + <colspec align="left"/>
  571 + <colspec align="left"/>
  572 + <colspec align="right"/>
  573 +
  574 + <thead>
  575 + <row valign="top">
  576 + <entry><emphasis role="bold">Propriedade</emphasis></entry>
  577 + <entry><emphasis role="bold">Descrição</emphasis></entry>
  578 + <entry><emphasis role="bold">Valor padrão</emphasis></entry>
  579 + </row>
  580 + </thead>
  581 + <tbody>
  582 + <row valign="top">
  583 + <entry>frameworkdemoiselle.security.authenticator.class</entry>
  584 + <entry>
  585 + <para>
  586 + Define a classe concreta utilizada como implementação da interface Authenticator
  587 + </para>
  588 + </entry>
  589 + <entry>
  590 + <emphasis>
  591 + nenhum, se houver apenas uma implementação o framework a detectará
  592 + automaticamente sem necessidade de definir essa propriedade
  593 + </emphasis>
  594 + </entry>
  595 + </row>
  596 +
  597 + <row valign="top">
  598 + <entry>frameworkdemoiselle.security.authorizer.class</entry>
  599 + <entry>
  600 + <para>
  601 + Define a classe concreta utilizada como implementação da interface Authorizer
  602 + </para>
  603 + </entry>
  604 + <entry>
  605 + <emphasis>
  606 + nenhum, se houver apenas uma implementação o framework a detectará
  607 + automaticamente sem necessidade de definir essa propriedade
  608 + </emphasis>
  609 + </entry>
  610 + </row>
  611 + </tbody>
  612 + </tgroup>
  613 + </informaltable>
232 </section> 614 </section>
233 - <caution> <para>O Demoiselle também oferece o componente  
234 - <ulink url="http://demoiselle.sourceforge.net/docs/demoiselle-guide-components/1.2.0/html/authorization-master.html">demoiselle-authorization</ulink>  
235 - que facilita o uso de segurança com JAAS. Obviamente, não é possível utilizá-los ao mesmo tempo. Há arquétipos Maven que já trazem esse componente  
236 - como dependência, por isso sempre confira o arquivo pom.xml e se for o caso retire essa dependência.</para> </caution>  
237 - 615 +
238 </chapter> 616 </chapter>
239 \ No newline at end of file 617 \ No newline at end of file