December 5th, 2014 by gilberto_ca

Visualizando arquivos de log no NetBeans

radhika. Viewing log files in NetBeans IDE
[online] Disponível na Internet via WWW. URL: https://blogs.oracle.com/NetBeansSupport/entry/netbeans_ide_log_file. Arquivo capturado em 05 de dezembro de 2014

Os diferentes arquivos de log que o usuário do NetBeans necessita verificar em caso de problema, e como visualizá-los através do próprio IDE:

  • O arquivo de log do NetBeans: Para visualizar o conteúdo deste arquivo acesse Menu Principal -> Exibir -> Log do IDE (ou diretamente $netbeans_userdir/var/log/messages.log). O conteúdo aparece na janela de saída com o título log do IDE
  • Os arquivos de log de Servidor: Para visualizar os arquivos de log de Servidor, mude para janela Serviços, expanda o nó Servidores, clique com o botão direito do mouse sobre o nó da instância, e selecione ‘Exibir Log do Servidor’.
  • Por exemplo, para o servidor de aplicações GlassFish Server Open Source que vem na instalação do NetBeans, na janela Serviços, expanda o nó Servidores -> GlassFish V4 e clique com o botão direito do mouse, e selecione ‘Exibir Log do Servidor’. O conteúdo aparece na janela de saída sob aba de título glassFish V4.
  • Observe que para um Servidor Tomcat registrado, clicar com o botão direito do mouse e selecionar ‘Visualizar saída do servidor’, exibirá o arquivo de log do servidor definido no arquivo de configuração server.xml. Este menu fica disponpível quando o servidor estiver em execução.
July 2nd, 2014 by gilberto_ca

Oracle JDK8 no OpenSUSE

Esta forma de instalação é mais resumida que a do post antigo e utiliza o formato comprimido (tar.gz).

Realize o download a partir deste local: Java SE Development Kit 8 Downloads, em um diretório de sua escolha – escolhi: Downloads.

Depois como super usuário (root) pelo Kconsole faça uso da seguinte sequência:

gilberto.andrade@A37710:~$ su -
Senha:
A37710:~ 
A37710:~ cd /usr/java
A37710:~ tar xvf ~/Downloads/jdk-8u5-linux-x64.tar.gz
A37710:~ chown -R root:root jdk1.8.0_05
A37710:~ rm latest
A37710:~ ln -s /usr/java/jdk1.8.0_05 /usr/java/latest
A37710:~ cd latest/bin
A37710:~ for bin in *; do update-alternatives --install /usr/bin/$bin $bin $(pwd)/$bin 1; done
A37710:~ cd ..
A37710:~ cd latest/jre/bin
A37710:~ for bin in *; do update-alternatives --install /usr/bin/$bin $bin $(pwd)/$bin 1; done
A37710:~ cd ..
A37710:~ cd ..
A37710:~ update-alternatives --install /usr/lib64/browser-plugins/javaplugin.so javaplugin /usr/java/latest/jre/lib/amd64/libnpjp2.so 1
A37710:~ update-alternatives --config java
A37710:~ update-alternatives --config javac
A37710:~ update-alternatives --config javaplugin
A37710:~

February 21st, 2013 by gilberto_ca

Instale Oracle JDK7 no openSUSE

Realize o download a partir deste local: Java SE Development Kit 7 Downloads, em um diretório de sua escolha – escolhi: /Softwares_usados/Tools/java/jdk/ .

Depois como super usuário (root) utilize a Ferramente de Gerencimanto de Software – Zypper - para instalar o pacote (arquivo RPM):

gilberto.andrade@A37710:~$ su -
Senha:
A37710:~ # cd /dados/D/Softwares_usados/Tools/java/jdk/
A37710:/dados/D/Softwares_usados/Tools/java/jdk # ll
total 439208
-rw-r----- 1 gilberto.andrade users   8405307 Feb 11 20:14 javafx-2_2_7-apidocs.zip
-rw-r--r-- 1 gilberto.andrade users  54426218 Oct 11 15:12 javafx_scenebuilder-1_1-beta-linux-x64.tar.gz
-rw-r--r-- 1 gilberto.andrade users 216263278 Jun 13  2012 javatutorials.zip
-rw-r----- 1 gilberto.andrade users  60768483 Feb 11 18:10 jdk-7u15-apidocs.zip
-rw-r----- 1 gilberto.andrade users 109860709 Feb 16 04:08 jdk-7u15-linux-x64.rpm
 
A37710:/dados/D/Softwares_usados/Tools/java/jdk # zypper install jdk-7u15-linux-x64.rpm

Vamos “avisar” o mecanismo do sistema que é responsável por estes serviços – update-alternatives- que existe uma nova versão do jdk instalada. O diretório (melhor dizendo, link) /usr/java/latest representa a versão mais recente instalada e irá apontar para última e mais nova versão:

A37710:/usr/java # ll
total 12
lrwxrwxrwx 1 root root   16 Feb 15 16:09 default -> /usr/java/latest
drwxr-xr-x 4 root root 4096 Feb 15 15:13 jdk1.7.0_07
drwxr-xr-x 3 root root 4096 Feb 21 14:36 jdk1.7.0_13
drwxr-xr-x 8 root root 4096 Feb 21 14:36 jdk1.7.0_15
lrwxrwxrwx 1 root root   21 Feb 21 14:36 latest -> /usr/java/jdk1.7.0_15

A partir do diretório latest/bin e latest/jre/bin realize as seguintes modificações:

A37710:/usr/java # cd latest/bin/
A37710:/usr/java/latest/bin # for bin in *; do update-alternatives --install /usr/bin/$bin $bin $(pwd)/$bin 20000; done
A37710:/usr/java/latest/bin # cd ..
A37710:/usr/java/latest # cd jre/bin/
A37710:/usr/java/latest/jre/bin # for bin in *; do update-alternatives --install /usr/bin/$bin $bin $(pwd)/$bin 20000; done
A37710:/usr/java/latest/jre/bin #

Por fim, atualizaremos o plugin java – javaplugin.so - para os navegadores instalados no sistema:

update-alternatives --install /usr/lib64/browser-plugins/javaplugin.so javaplugin /usr/java/latest/jre/lib/amd64/libnpjp2.so 20000

Olhe com atenção pois utilizamos como referência para atualizar o update-alternatives o caminho base /usr/java/latest.
Por quê? Você sabe explicar?

July 13th, 2012 by gilberto_ca

Java – Boas referências online

Tenho alguns livros sobre Java, mas com as mudanças que a linguagem sofreu nos três últimos anos tenho por mim que minhas referências estão desatualizadas. Meu grande interesse é entender melhor os detalhes que muitos programadores (vindos de outra linguagem ou não) ignoram – seja por desconhecimento, seja por desinteresse, pois o arcabouço de APIs Java é muito amplo.

Enquanto realizo minha tarefa diária – implementando ou corrigindo código – costumo manter ao meu lado algumas referências e hoje vou postar as que costumo consultar via internet. Vamos a elas:

May 18th, 2012 by gilberto_ca

É um PostgreSQL! Não, é um MSSql! Não, é um DB2! [h2 modo compatibilidade]

Calma pessoal, é apenas o banco H2 em modo compatibilidade! Imagine
que você acabou levando trabalho pra casa (Novidade!!!) mas se
esqueceu que em casa vc não possui o ambiente – banco de dados –
desenvolvimento semelhante ao do trabalho. Em meu caso um servidor de
banco de dados PostgreSQL.

O que isso tem haver com o banco de dados H2? Diferentemente de um
Postgresql, um MS Sql ou Oracle o H2 é um banco de dados leve e de
fácil instalação, podendo até executá-lo sem a necessidade de uma
instalação propriamente dita.

Mas como isso funciona?

Há dua formas de se beneficiar desta característia. A primeira é
utilizar o driver jdbc do próprio H2, utilizando o parâmetro MODE na
URL de conexão:

jdbc:h2:file:data/teste;create=true;MODE=PostgreSQL;DB_CLOSE_DELAY=-1

Assim você poderia recriar as estruturas do banco por script ou
ativando a criação das entidades no provedor de persistência – caso
utilize JPA. Veja que as estruturas – tabelas, views, sequências, etc
- não teriam que ser ajustadas por estar utilizando o H2. O banco H2
entende o dialeto, por assim dizer, do banco a ser “emulado” pelo
parâmetro MODE.

A segunda maneira, por sinal mais interessante, é não fazer nada!
Como assim? Você provavelmente se questiona! É verdade, você não
mexe em nada do seu projeto – que é um banco específico, no meu caso o
PostgreSQL. Você continua utlizando o driver, a URL do seu banco e
deixa o H2 fazer o resto. Vamos ver?
Suponha que sua forma de conexão seja a seguinte:

<dependencies>
	<dependency>
		<groupId>postgresql</groupId>
		<artifactId>postgresql</artifactId>
		<version>8.1-408.jdbc3</version>
	</dependency>
</dependencies>
<properties>
	<!-- Default Database Connection-->
	<jdbc.url>jdbc:postgresql://localhost:5435/teste</jdbc.url>
	<jdbc.driverClassName>org.postgresql.Driver</jdbc.driverClassName>
	<jdbc.username>teste</jdbc.username>
	<jdbc.password>teste</jdbc.password>
</properties>

Para funcionar precisamos ter um servidor PostreSQL rodando
localmente, certo? Pois bem, vamos iniciar e estabelecer um servidor
PostgreSQL através do H2. Para facilitar as coisas, vamos criar um
profile
que nos auxiliará nesta tarefa:

<profiles>
<profile>
	<id>h2</id>
	<activation>
		<activeByDefault>false</activeByDefault>
	</activation>
	<dependencies>
		<dependency>
			<groupId>postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>8.1-408.jdbc3</version>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>1.3.166</version>
		</dependency>
	</dependencies>
</profile>
</profiles>

Agora a “grande sacada” do H2, abra dois terminais: um para rodar o
servidor e a outra para você trabalhar normalmente com o maven. Em uma
delas iremos iniciar o servidor:

mvn -P h2 exec:java -Dexec.mainClass="org.h2.tools.Server" -Dexec.args="-properties data -baseDir data"

Após este comando, você terá a sua disposição uma interface – via
navegador – a qual lhe permitirá escolher em qual MODE rodar o
servidor.

H2 Admin Interface


Ao conectar àquela configuração definida incialmente, teremos outra
interface de administração. Aqui poderemos administrar nosso “banco
PostgreSQL”

H2 Admin Console


Acesse este banco por sua aplicação ou por qualquer outro cliente
jdbc – por exemplo o squirrel. Lembre-se você estará acessando um
banco PostgreSQL!

March 26th, 2012 by gilberto_ca

Alterne entre versões Java facilmente [update-alternatives] parte 2

A um tempo atrás escrevi sobre o utilitário de sistema update-alternatives e mostrei como alternar entre versões do Java usando o mesmo. Naquele mesmo post mostrei que o Java já havia sido instalado e configurado pelo sistema de gerenciamento de pacotes pre-definido – Yast. Como já é de conhecimento de alguns a Oracle mudou a forma de licenciamento do Java e com isso a maioria das distribuições – senão todas – optaram por retirar o Java distribuído pela Oracle de seus repositórios. Com isso, se você precisar instalar a versão Java da Oracle terá que fazê-la manualmente.

Antes de começar, quero notificar aos usuários do navegador Chromium que como eles tive dificuldades, no início, para fazê-lo funcionar com Java ao acessar o site do Banco do Brasil. Para confirmar este problema é só fazer uma pesquisa no Google usando a seguinte sentença: chromium banco do brasil. Então para a felicidade geral nação “chromiumana”, relato que esta maneira manual aqui demonstrada soluciona este pequeno problema.

Então vamos lá!
Os passos são esses:

  • Baixe a versão RPM do site da Oracle – baixei a versão jre-7u3-linux-i586.rpm;
  • Instale o jre com yast2, zypper, ou com um duplo clique no rpm pelo dolphin ou nautilus:
    SUGEP265338:~ # zypper in jre-7u3-linux-i586.rpm
  • Agora precisamos adicionar esta instalação às alternativas já instaladas, de forma a disponibilizá-la como uma opção:
    SUGEP265338:~ # update-alternatives --install /usr/bin/java java /usr/java/jre1.7.0_03/bin/java 40
  • Faremos o mesmo para o plugin java. Esta opção é muito importante pois estabelece qual versão Java para navegação web estaremos usando:
    SUGEP265338:~ # update-alternatives --install /usr/lib/browser-plugins/javaplugin.so javaplugin /usr/java/jre1.7.0_03/lib/i386/libnpjp2.so 40
  • Bom, agora vem a parte mais fácil que é, como escrevi no primeiro post, alternar entre tais versões:
    SUGEP265338:~ # update-alternatives --config java
    There are 2 choices for the alternative java (providing /usr/bin/java).
     
      Selection    Path                                     Priority   Status
    ------------------------------------------------------------
    * 0            /usr/lib/jvm/jre-1.6.0-openjdk/bin/java   17105     auto mode
      1            /usr/java/jre1.7.0_03/bin/java            40        manual mode
      2            /usr/lib/jvm/jre-1.6.0-openjdk/bin/java   17105     manual mode
     
    Press enter to keep the current choice[*], or type selection number: 1
    update-alternatives: using /usr/java/jre1.7.0_03/bin/java to provide /usr/bin/java (java) in manual mode.
    SUGEP265338:~ #
  • E finalmente, o mais importante, o plugin para os navegadores web:
    SUGEP265338:~ # update-alternatives --config javaplugin
    There are 2 choices for the alternative javaplugin (providing /usr/lib/browser-plugins/javaplugin.so).
     
      Selection    Path                                        Priority   Status
    ------------------------------------------------------------
    * 0            /usr/lib/IcedTeaPlugin.so                    17106     auto mode
      1            /usr/java/jre1.7.0_03/lib/i386/libnpjp2.so   40        manual mode
      2            /usr/lib/IcedTeaPlugin.so                    17106     manual mode
     
    Press enter to keep the current choice[*], or type selection number: 1
    update-alternatives: using /usr/java/jre1.7.0_03/lib/i386/libnpjp2.so to provide /usr/lib/browser-plugins/javaplugin.so (javaplugin) in manual mode.
    SUGEP265338:~ #

Pronto! Feche o navegador e faça um teste. Até a próxima!

Atualização(12/07/2012): Hoje pela manhã, procurando por mudanças que torne o script update-alternatives compatível com o jdk 1.7, me deparei com uma forma bem mais simples de instalar manualmente o jdk Oracle. Veja:

 
zypper install jdk-7-linux-x64.rpm
cd /usr/java/jdk1.7.0/bin
for bin in *; do update-alternatives --install /usr/bin/$bin $bin $(pwd)/$bin 20000; done

Agora o javaplugin para o navegador:

update-alternatives --install /usr/lib64/browser-plugins/javaplugin.so javaplugin /usr/java/jdk1.7.0/jre/lib/amd64/libnpjp2.so 20000

Usei a versão 64bits mas o procedimento vale também para 32bits.

April 7th, 2011 by gilberto_ca

Apache Shiro Parte 1 – básico

Este post é uma tradução livre do artigo “ Apache Shiro Part 1 – Basics “, publicado por Meri em 27 de março 2011


ATUALIZAÇÃO: duas novas seções adicionadas – tratamento de erros e hashing de senhas.

Apache Shiro, inicialmente chamado JSecurity, é um framework de segurança desenvolvido em java. Foi aceito e tornou-se um projeto Apache de nível superior em 2010. Tem como objetivo ser poderoso e fácil de usar.

O projeto está em constante desenvolvimento e com listas de e-mails ativas para usuários e desenvolvedores. Áreas mais importantes estão documentadas em sua página web. No entanto, existem algumas lacunas na documentação. Não é possível aprender a usar o máximo dos recursos do Shiro somente com a documentação. Felizmente, o código é bem documentado e onde o testei, ela foi de fácil leitura.

Principais recursos do projeto Shiro são:


  • autenticação,

  • autorização,

  • criptografia,

  • gerenciamento de sessão.

Neste artigo tentaremos demonstrar vários recursos do Shiro. Vamos começar com uma simples aplicação sem segurança e então adicionaremos recursos de segurança. Todo código está disponível no projeto SimpleShiroSecuredApplication hospedado no Github.

Aplicação sem Segurança

O código da aplicação sem segurança está localizado no ramo(branch) unsecured_application.
A aplicação representa um sistema interno para uma companhia fictícia. A companhia tem quatro departamentos:


  • administradores(administrators),

  • reparadores(repairmen),

  • cientistas(scientists),

  • vendedores(sales).

Cada departamento tem sua própria página. Cada página contém botões que serão usados por usuários em sua atividade. Quando o usuário pressiona o botão, o trabalho é realizado. Por exemplo, qualquer reparador pode acessar a página reparadores(repairmen) e pressionar o botão “Reparar Refrigerador(Repair Refrigerator)”. O botão repara refrigerador e mostra mensagem de sucesso.

Cada usuário tem sua própria página de gerenciamento de conta. Esta página de gerenciamento contém informações privadas do usuário. Como a aplicação sem segurança não tem usuários ainda, a página de gerenciamento de conta não faz nada. Adicionalmente, há uma página que contém todas funções da aplicação. Tudo que alguém pode fazer é possível ser feito nesta página.

Qualquer pessoa pode fazer qualquer coisa e ver todas as páginas. A aplicação exemplo é executada na classe de teste RunWaitTest. Não é uma boa prática usar teste de unidade desta forma, mas isso não é importante agora. Se você executar a classe a aplicação estará disponível no endereço (url) http://localhost:9180/simpleshirosecuredapplication/.

Adicionando Autenticação

Primeiro, temos que verificar a identidade do usuário. A mais fácil e padronizada forma de autenticação é feita por senha e nome usuário. Usuário preenche o seu nome de usuário e senha e o sistema verifica se os valores fornecidos combinam com alguma conta de usuário.

Para aplicações mais simples, é suficiente armazenar nome e senha de usuários em arquivos de texto puro. Em um cenário mais realista, o nome e senha são armazenados em um mecanismo de persistente or a verificação é feita por outro sistema como ldap ou active directory. Shiro suporta todos os métodos de autenticação mencionados. Se os recursos de autenticação pré-existentes não são suficientes, é possível estender o framework com sua própria implementação de verificação.

Neste capítulo, iremos adicionar autenticação baseada em nome de usuário e senha na aplicação. Nome de usuário e senha serão armazenados no arquivo de inicialização do Shiro, o qual é texto e estático.

Novos requisitos:
É possível a entrada e saída de usuários(log in/out). A aplicação será acessível somente para usuários registrados. Usuário com autenticação sem erros é redirecionado para sua própria página de gerenciamento de conta. Todas as páginas e funções da aplicação serão acessíveis para qualquer usuário autenticado.
Passos necessários:


  • adicionar Apache Shiro,

  • criar página de autenticação(log in),

  • configurar usuários e senhas,

  • criar página de saída(log out).

Adicionar Apache Shiro

Shiro é integrado à aplicação web através de filtros servlet. Um filtro intercepta requisições e respostas antes do servlet e executa todas as tarefas necessárias (como a identificação do usuário atualmente autenticado, anexar o usuário ao thread corrente, …). Filtros Shiro pré-definidos fornecem recursos de segurança básicos, como:


  • força a autenticação do usuário(log in),

  • força ssl,

  • verificação dos direitos de acesso à página.

Se você quiser aprender mais sobre filtros Shiro pré-definidos, um bom lugar para começar é a enumeração DefaultFilter. Ela lista todos os filtros Shiro pré-definidos disponíveis. Se estes não forem suficientes para suas necessidades, você pode criar um personalizado.

Usaremos o filtro altamente configurável IniShiroFilter. Ele lê a configuração Shiro a partir do arquivo ini e inicializa o framework de segurança. Ele não executa qualquer verificação de segurança. Verificação de segurança, autenticação de usuário, verificação de protocolo, etc. são todos transferidos(delegados) tanto para o filtro Shiro pré-definido quanto para o filtro personalizado(outra implementação). O filtro IniShiroFilter apenas os inicializa.

A configuração ini é descrita na documentação e no javadoc. O arquivo de configuração ini tem quatro seções:


  • Seção [main] contém a inicialização do Shiro. Filtros e objetos personalizados são configurados aqui.

  • Seção [users] define usuários, senhas e perfis de usuário(roles).

  • Seção [roles] associa perfis(roles) com permissões.

  • Seção [urls] especifica direitos de acesso às páginas da aplicação (urls). É feito ligando filtro tanto pré-definido quanto personalizado às urls

Adicione Apache Shiro como dependência ao arquivo pom.xml:

<properties>
    <shiro.version>1.1.0</shiro.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>${shiro.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>${shiro.version}</version>
    </dependency>
</dependencies>

Crie o arquivo Shiro.ini e o coloque no classpath. Configure o arquivo web.xml para chamar o filtro IniShiroFilter antes de cada requisição:

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
    <init-param>
        <param-name>configPath</param-name>
        <param-value>classpath:Shiro.ini</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Criar Página de Autenticação(Log in)

A página de autenticação é uma simples página html contendo um botão submissão, nome de usuário e senha. A funcionalidade de autenticação é tratada pelo filtro Shiro authc pré-definido. O filtro autch permite acesso à página (url) somente a usuários autenticados. Se o usuário não está autenticado, o filtro o redirecionará para a página de autenticação (log in).

Crie a página login.jsp:

<form name="loginform" action="" method="post">
    <table align="left" border="0" cellspacing="0" cellpadding="3">
        <tr>
            <td>Username:</td>
            <td><input type="text" name="user" maxlength="30"></td>
        </tr>
        <tr>
            <td>Password:</td>
            <td><input type="password" name="pass" maxlength="30"></td>
        </tr>
        <tr>
            <td colspan="2" align="left"><input type="checkbox" name="remember"><font size="2">Remember Me</font></td>
        </tr>
        <tr>
            <td colspan="2" align="right"><input type="submit" name="submit" value="Login"></td>
        </tr>
    </table>
</form>

Habilite o filtro authc para todas as páginas da aplicação:

[main] 
# specify login page
authc.loginUrl = /simpleshirosecuredapplication/account/login.jsp
 
# name of request parameter with username; if not present filter assumes 'username'
authc.usernameParam = user
# name of request parameter with password; if not present filter assumes 'password'
authc.passwordParam = pass
# does the user wish to be remembered?; if not present filter assumes 'rememberMe'
authc.rememberMeParam = remember
 
# redirect after successful login
authc.successUrl  = /simpleshirosecuredapplication/account/personalaccountpage.jsp
 
[urls]
# enable authc filter for all application pages
/simpleshirosecuredapplication/**=authc

Atualização: Shiro automaticamente executa a equiparação(comparação) de caminho(path matching) relativa ao contexto. Como a aplicação SimpleShiroSecuredApplication não tem o caminho do contexto definido, caminhos completos no arquivo Shiro.ini são necessários. No entanto, se o contexto da aplicação fosse definido para /simpleshirosecuredapplication, então os caminhos poderiam ser relativos, por exemplo, /**=authc ou /account/personalaccountpage.jsp.

Como não é seguro enviar nome de usuário e senha pela rede, devemos forçar autenticações com o protocolo ssl. O filtro ssl faz exatamente isso. Ele tem um parâmetro opcional: número da porta ssl. Se o parâmetro porta(port) for omitido, ele usa a porta ssl pré-definida 443.

Antes de configurar o protocolo ssl no Shiro, precisamos habilitá-lo no servidor web. Como fazer isso, depende do servidor web. Iremos demonstrar como habilitá-lo no Jetty. Primeiro, crie um keystore com o certificado auto assinado:

keytool -genkey -keyalg RSA -alias jetty -keystore keystore -storepass secret -validity 360 -keysize 2048

Responda todas questões e no final pressione ENTER, assim o keystore senha e a chave senha serão o mesmo.

Segundo, adicione o keystore ao projeto e configure o servidor Jetty para usar o protocolo ssl. O código java está disponível na classe AbstractContainerTest.

Agora é possível configurar o filtro ssl no arquivo Shiro.ini:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443],authc
# enable authc filter for the all application pages; as Shiro reads urls from up to down, must be last
/simpleshirosecuredapplication/**=authc

Configurar Usuários e Senhas

A aplicação SimpleShiroSecuredApplication estará agora disponível somente para usuários autenticados. Assim, é necessário adicionar alguns usuários de forma que algumas pessoas tenham acesso à aplicação.
A configuração é feita na seção [users] do arquivo Shiro.ini. O formato das entradas da seção é:

username = password, roleName1, roleName2, ..., roleNameN

A seguinte seção cria sete usuários, todos com a mesma senha ‘heslo’:

[users]
administrator=heslo,Administrator
friendlyrepairmen=heslo,repairmen
unfriendlyrepairmen=heslo,repairmen
mathematician=heslo,scientist
physicien=heslo,scientist
productsales=heslo,sales
servicessales=heslo,sales

Agora é possível ser autenticado e ter acesso à aplicação. No entanto, nenhuma mensagem de erro razoável é mostrada se o usuário comete um erro. Além disso, as senhas são armazenadas em arquivo texto.

Tratamento de Erro

Se o usuário comete um erro ao fazer a autenticação (log in), o Shiro o redireciona de volta para a página de login. A página parece exatamente a mesma de antes, o que pode confundir o usuário.

Novo requerimento:
Mostrar mensagem de erro após cada tentativa de autenticação(log in) sem êxito.

Toda vez que ocorrer um erro de autenticação, uma exceção é lançada. Por definição, o filtro de autenticação captura a exceção e armazena nome da classe (exceção) em um parâmentro da requisição (request). Como desejamos personalizar os dados enviados à página, teremos que estender o filtro pré-definido FormAuthenticationFilter e sobrescrever o método setFailureAttribute:

@Override
protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
  String message = ae.getMessage();
  request.setAttribute(getFailureKeyAttribute(), message);
}

Substitua o filtro pré-definido FormAuthenticationFilter por VerboseFormAuthenticationFilter e o configure para usar o atributo de requisição (request) ‘simpleShiroApplicationLoginFailure’ para armazenar a informação do erro:

[main]
# replace form authentication filter with verbose filter
authc = org.meri.simpleshirosecuredapplication.servlet.VerboseFormAuthenticationFilter
# request parameter with login error information; if not present filter assumes 'shiroLoginFailure'
authc.failureKeyAttribute=simpleShiroApplicationLoginFailure

Mostrar o erro na página login.jsp:

<%
  String errorDescription = (String) request.getAttribute("simpleShiroApplicationLoginFailure");
  if (errorDescription!=null) {
%>
Login attempt was unsuccessful: <%=errorDescription%>
<%
  }
%>

Cuidado: uma aplicação real não deve apresentar muitas informações de erro de autenticação. Uma mensagem como “tentativa de logon sem sucesso.”, com nenhuma informação adicional é geralmente suficiente.

Hashing de Senhas

Na versão atual da aplicação, todas as senhas estão, ainda, em texto puro. É melhor armazenar e comparar somente o hashing da senha.

Objetos responsáveis por autenticação são chamados de realms. Por padrão, Shiro usa o IniRealm com comparador de senha plugável para comparar senhas. Iremos substituir as senhas no ini por suas correspondentes hasheadas com SHA-256 e configurar o IniRealm para usar este comparador de senhas.

Gerar o hash SHA-256 da senha:

import org.apache.shiro.crypto.hash.Sha256Hash;
 
public static void main(String[] args) {
    Sha256Hash sha256Hash = new Sha256Hash("heslo");
    System.out.println(sha256Hash.toHex());
}

Configurar o Shiro para comparar senha trasnformada(hashing) ao invés da própria senha:

[main] 
# define matcher matching hashes instead of passwords
sha256Matcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
sha256Matcher.hashAlgorithmName=SHA-256
 
# enable matcher in iniRealm (object responsible for authentication)
iniRealm.credentialsMatcher = $sha256Matcher

Substituir as senhas dos usuários por senhas trasnformadas(hashing):

[users]
administrator=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, Administrator
friendlyrepairmen=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, repairmen
unfriendlyrepairmen=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, repairmen
mathematician=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, scientist
physicien=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,  scientist
productsales=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,        sales
servicessales=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,  sales

Nota: não é possível especificar SALT no arquivo de configuração ini.

Criar Página de Saída(Log out)

Qualque aplicação que tenha recursos de autenticação deveria também ter o recurso de saída. Terminar uma sessão corrente com Shiro é fácil, use o comando:

//acquire currently logged user and log him out
SecurityUtils.getSubject().logout();

A página de saída(Log out) então fica assim:

<%@ page import="org.apache.shiro.SecurityUtils" %>
<% SecurityUtils.getSubject().logout();%>
You have succesfully logged out.

Adicionar Autorização

Concluiremos esta primeira parte adicionando autorização à aplicação. Começamos limitando o acesso às páginas aos usuários. Nenhum usuário deveria ser capaz de ver páginas de outros departamentos. Fornecendo assim, somente segurança parcial ao projeto, pois o usuário ainda é capaz de usar a página com “todas as funções da aplicação” ou editar o endereço (url) no navegador para realizar qualquer ação. Nós a chamaremos de autorização em nível de página.

Então, limitaremos a habilidade dos usuários para realizar ações próprias. Mesmo que abra a página com “todas as funções da aplicação” ou edite o endereço (url) no navegador, ele poderá realizar somente funções específicas de seu departamento. Nós a chamaremos de autorização em nível de função.

Novos requisitos: o usuário não é capaz de ver páginas de departamentos que não pertence. O usuário é capaz de realizar somente funções de seu departamento. Uma exceção a essa regra é o administrador, que pode realizar funções administrativas e de reparação.

Página de Autorização

Autorização em nível de página é feita com filtro de perfis(roles).
Parâmetro parte do filtro pode conter qualquer número de perfis. Usuário autenticado pode acessar a página somente se ele tem todas os perfis fornecidos.

Como de costume, o filtro de perfis(roles) é configurado no arquivo Shiro.ini:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443],authc
 
# only users with some roles are allowed to use role-specific pages 
/simpleshirosecuredapplication/repairmen/**=authc, roles[repairman]
/simpleshirosecuredapplication/sales/**=authc, roles[sales]
/simpleshirosecuredapplication/scientists/**=authc, roles[scientist]
/simpleshirosecuredapplication/adminarea/**=authc, roles[Administrator]
 
# enable authc filter for the all application pages; as Shiro reads urls from up to down, must be last
/simpleshirosecuredapplication/**=authc

Teste se a segurança funciona: entre como um usuário de vendas, clique home, clique no link ‘repairmen page’. Você verá um erro feio.

Nós terminamos a página de autorização e substituimos o erro redirecionando-o para uma página de erro. Os filtros pré-definidos do Shiro possuem a propriedade unauthorizedUrl. Em caso de acesso não autorizado, o filtro redirecionará o usuário para um endereço (url) específico.

[main]
# redirect to an error page if user does not have access rights
roles.unauthorizedUrl = /simpleshirosecuredapplication/account/accessdenied.jsp

accessdenied.jsp:

<body>
Sorry, you do not have access rights to that area.
</body>

Autorização de Funções

Todas as páginas departamentais estão protegidas agora. No entanto, qualquer usuário pode ainda realizar qualquer função na página com “todas as funções da aplicação”. Além disso, qualquer usuário autenticado pode editar endereço (url) e assim fazer qualquer ação. Por exemplo, se você entrar como vendedor e colocar
https://localhost:8443/simpleshirosecuredapplication/masterservlet?action=MANAGE_REPAIRMEN na url, a aplicação irá realizar a função gerenciar reparadores também (e então irá dispará a exceção: null point, mas a violação de segurança já foi feita).
Atribuimos uma úncia permissão para cada função. Elas estão divididas em grupos:


  • todas as permissões estão no grupo “functions”,

  • todas as permissões administrativas estão no grupo “manage”,

  • todas as permissões reparação estão no grupo “repair”,

  • todas as permissões venda estão no grupo “sale”,

  • todas as permissões ciência estão no grupo “science”.

Shiro suporta permissões de múltiplos níveis representadas como strings. Níveis são separados com o símbolo ‘:’. p.e. “functions:manage:repairmen” tem três níveis: “functions”, “manage” e “repairman”. Permissões de múltiplos níveis permitem facilmente o agrupamento de permissões. Por exemplo, o grupo science pertence ao grupo functions e contém três permissões:


  • functions:science:research,

  • functions:science:writearticle,

  • functions:science:preparetalk.


A classe Ações verifica as permissões do usuário autenticado(log in) antes de fazer seu trabalho:

public String doIt() {
    String neededPermission = getNeededPermission();
    // acquire logged user and check permission
    if (SecurityUtils.getSubject().isPermitted(neededPermission))
        return "Function " + getName() + " run succesfully.";
 
    throw new UnauthorizedException("Logged user does not have " + neededPermission + " permission");
}

NOTA: Outro modo de se alcançar o mesmo objetivo é através de anotações.

O servlet PerformFunctionAndGoBackServlet captura exceções de autorização e as converte em mensagem de erro:

private String performAction(String actionName) {
    try {
        Actions action = findAction(actionName);
        String result = action == null ? null : action.doIt();
        log.debug("Performed function with result: " + result);
        return result;
    } catch (ShiroException ex) {
        log.debug("Function failed with " + ex.getMessage() + " message.");
        return "Error: " + ex.getMessage();
    }
}

Finalmente, precisamos configurar as permissões para os perfis no arquivo Shiro.ini. Shiro suporta curingas para permissões de múltiplo nível. Assim, não temos que especificar cada permissão departamental em separado:

[roles]
# members of departments should be able to perform all departmental functions
sales=functions:sale:*
scientist=functions:science:*
repairman=functions:repair:*
 
# administrators are able to do all management functions and repair functions
Administrator=functions:manage:*,functions:repair:*

Você pode agora acessar a página “todas as funções da aplicação” e testar as funções.
Se um usuário autenticado não tiver a permissão requerida, uma mensagem de erro aparecerá no topo da página. Além disso, se você fizer a autenticação (log in) como vendedor e tentar hackear
https://localhost:8443/simpleshirosecuredapplication/masterservlet?action=MANAGE_REPAIRMEN, você verá uma mensagem de erro no console (em vez de uma mensagem de sucesso).

Fim

A aplicação final está disponível no ramo(branch) ‘static_authentication_and_authorization’ hospedado no Github.

Na segunda parte iremos criar um realm personalizado e mover usuários, senhas, perfis(roles) e permissões do arquivo ini para um banco de dados.

July 21st, 2010 by gilberto_ca

Alterne entre versões Java facilmente [Netbeans 6.*]

Outro dia escrevi como alterner entre versões Java facilmente utilizando o utilitário de sistema operacional update-alternatives. Aquele post tem uma perspectiva do lado do servidor onde estão instalados servidores de aplicação java ou mesmo aplicativos e o administrador/desenvolvedor precisa testar como estes artefatos mencionados se comportariam em cada versão.

Hoje vou relatar outra maneira de alternar entre versões java em perspectiva do lado do desenvolvedor. Aqui na secretaria, podemos escolher entre Netbeans e Eclipse como ambientes de desenvolvimento, desde que o projeto seja gerenciado pela ferramenta de construção Maven.

Minha escolha, assim como de mais alguns colegas foi o Netbeans 6.8. Vejamos então como configurar o IDE Netbeans para facilitar a traca de versões java para compilar ou rodar aplicativos.
Tanto para configurar ou mesmo alternar a versão do java utilizado pode-se utilizar o seguinte caminho:
Project’s properties->Build:compile .
A partir deste diálogo, você poderá alternar de versão através “Java Plataform” ou gerenciar/adicionar/remover versões através da opção “Manage Java Plataforms”

Lembrando que antes disso precisamos instalar as versões que desejamos utilizar.

July 8th, 2010 by gilberto_ca

Testes de Unidade em Paralelo[Maven|JUnit]

Este artigo no Dzone explica detalhadamente como executar testes em paralelo utilizando Maven e JUnit.

Qual a justificativa desta característica? Ora, imagine uma bateria de testes que acessa banco de dados, usa um servidor web  embarcado, ler longos arquivos xml, etc. Vê-se que nestes tipos de testes há bastante processamento e consequentemente demora-se mais. Com essa opção, execução em paralelo, obtemos melhor velocidade – performance.