Commit cbed5367285694954990d5903812bbd79bf27192
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 | 1 | <?xml version='1.0' encoding="utf-8"?> |
| 2 | 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 | 4 | <chapter id="security"> |
| 5 | 5 | |
| 6 | 6 | <title>Segurança</title> |
| ... | ... | @@ -9,19 +9,21 @@ |
| 9 | 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 | 10 | discussões nas equipes de desenvolvimento: controle de acesso. Assim como tudo relacionado ao framework, a |
| 11 | 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 | 13 | </para> |
| 15 | 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 | 16 | interfaces e anotações que definem o comportamento básico da implementação. |
| 18 | 17 | </para> |
| 19 | 18 | |
| 20 | 19 | <section> |
| 21 | 20 | <title>Configurando</title> |
| 21 | + | |
| 22 | 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 | 25 | </para> |
| 26 | + | |
| 25 | 27 | <programlisting role="XML"><![CDATA[<beans xmlns="http://java.sun.com/xml/ns/javaee" |
| 26 | 28 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 27 | 29 | xsi:schemaLocation="http://java.sun.com/xml/ns/javaee |
| ... | ... | @@ -31,208 +33,584 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee |
| 31 | 33 | <class>br.gov.frameworkdemoiselle.security.RequiredRoleInterceptor</class> |
| 32 | 34 | </interceptors> |
| 33 | 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 | 96 | </section> |
| 35 | 97 | |
| 36 | 98 | <section> |
| 37 | 99 | <title>Autenticação</title> |
| 38 | 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 | 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 | 105 | </para> |
| 44 | 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 | 109 | estão definidos os métodos responsáveis por gerenciar os mecanismos de autenticação como, por exemplo, executar |
| 48 | 110 | login/logout de usuários e verificar se os mesmos estão ou não autenticados. |
| 49 | 111 | </para> |
| 50 | 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 | 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 | 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 | 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 | 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 | 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 | 141 | </section> |
| 93 | 142 | |
| 94 | 143 | <section> |
| 95 | 144 | <title>Autorização</title> |
| 96 | 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 | 153 | formas: |
| 100 | 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 | 156 | <listitem><para>Permissão por papel, através da anotação @RequiredRole</para></listitem> |
| 103 | 157 | </itemizedlist> |
| 104 | 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 | 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 | 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 | 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 | 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 | 405 | </para> |
| 406 | + | |
| 137 | 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 | 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 | 460 | }]]></programlisting> |
| 461 | + | |
| 153 | 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 | 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 | 489 | </section> |
| 165 | 490 | |
| 166 | - <section> | |
| 491 | + <section id="criando_implementacao_seguranca"> | |
| 167 | 492 | <title>Criando sua implementação</title> |
| 493 | + | |
| 168 | 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 | 497 | </para> |
| 498 | + | |
| 171 | 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 | 503 | </para> |
| 504 | + | |
| 176 | 505 | <programlisting role="JAVA"><![CDATA[public class MeuAuthenticator implements Authenticator { |
| 177 | 506 | |
| 178 | 507 | @Override |
| 179 | 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 | 510 | return true; |
| 182 | 511 | } |
| 183 | 512 | |
| 184 | 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 | 523 | @Override |
| 191 | 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 | 528 | }]]></programlisting> |
| 195 | 529 | <programlisting role="JAVA"><![CDATA[public class MeuAuthorizer implements Authorizer { |
| 196 | 530 | |
| 197 | 531 | @Override |
| 198 | 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 | 534 | return false; |
| 201 | 535 | } |
| 202 | 536 | |
| 203 | 537 | @Override |
| 204 | 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 | 540 | return false; |
| 207 | 541 | } |
| 208 | 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 | 544 | <para> |
| 217 | 545 | Pronto! Sua aplicação já possui uma implementação de segurança definida. |
| 218 | 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 | 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 | 560 | </para> |
| 561 | + | |
| 225 | 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 | 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 | 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 | 616 | </chapter> |
| 239 | 617 | \ No newline at end of file | ... | ... |