Introdução ao JBoss AS 7.1 – Parte 2

Postado em Atualizado em

Update Novembro de 2012.

Galera para esse post vocês podem utilizar a versão final do JBoss 7 que não vai fazer muita diferença.

http://download.jboss.org/jbossas/7.1/jboss-as-7.1.1.Final/jboss-as-7.1.1.Final.zip

Continuando o post anterior https://jbossdivers.wordpress.com/2012/01/20/introducao-ao-jboss-as-7-parte-1/, hoje o objetivo será criar um  novo data source e um domínio de segurança baseado em banco de dados com a senha escriptada.

Como o nosso foco aqui é o JBoss AS 7, utilize o post https://jbossdivers.wordpress.com/2011/08/29/instalando-mysql-5-5-on-centos-5-6/, para se ambientar com o MySQL. Crie um banco de dados chamado db_security. Vamos utiliza-lo para armazenar os nossos roles e passwords.

1 – Instalando um Driver JDBC / MySQL como Módulo

Devemos realizar o download do driver JDBC para o nosso banco de dados, que no caso é o MySQL  5.

O driver pode se baixado no seguinte endereço: http://dev.mysql.com/downloads/connector/j/

A estrutura de diretórios do nosso módulo deve ser criada conforme exemplificada abaixo:

    mkdir -p jboss-as-7.1.0.CR1/modules/com/mysql/main

O diretório “main”, conterá os arquivos mysql-connector-java-5.1.18-bin.jar e o module.xml.

Para copiar o driver execute:

    cp mysql-connector-java-5.1.18-bin.jar /jboss-as-7.1.0.CR1/modules/com/mysql/main/

O Próximo passo, é criar o arquivo module.xm

    vim jboss-as-7.1.0.CR1/modules/com/mysql/main/module.xml

Inserindo o conteúdo abaixo:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
   <resources>
      <resource-root path="mysql-connector-java-5.1.18-bin.jar"/>
   </resources>
   <dependencies>
      <module name="javax.api"/>
    </dependencies>
</module>

Agora vamos fazer com o que o JBoss AS 7,  reconheça o  novo módulo de Data Source. Para isso devemos editar o arquivo standalone.xml, para isso execute:

    vim jboss-as-7.1.0.CR1/standalone/configuration/standalone.xml

O “subsystem”  <subsystem xmlns=”urn:jboss:domain:datasources:1.0″>, deve ser editado, e o conteúdo abaixo deve ser inserido:

<!--<datasources> -->

<datasource jndi-name="java:/MySQLDS" pool-name="MyPool" enabled="true" jta="true" use-java-context="true" use-ccm="true">
   <connection-url>jdbc:mysql://localhost:3306/db_security</connection-url>
   <driver>mysql</driver>
   <security>
     <user-name>usuario_database</user-name>
     <password>senha_database</password>
   </security>
   <statement>
       <prepared-statement-cache-size>100</prepared-statement-cache-size>
       <share-prepared-statements/>
   </statement>
</datasource>

<!--<drivers>-->
   <driver name="mysql" module="com.mysql"/>
<!--</drivers>-->

<!--</datasources>-->

Reinicie o JBoss e o datasource para o MySQL estará disponível.

Você deverá ver algo pareçido com a mensagem abaixo:

 15:33:51,221 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-3) JBAS010400: Bound data source [java:/MySQLDS]</em>

2 – Criando Domínio de Segurança Baseado em Banco de Dados com a Senha do Data Source Encriptada

A primeira coisa a ser feita é gerar a senha do banco de dados utilizando um algoritmo do Picketbox. Para isso execute os comandos abaixo:

  cd  $JBOSS_HOME$
  java -cp modules/org/jboss/logging/main/jboss-logging-3.1.0.CR2.jar:modules/org/picketbox/main/picketbox-4.0.6.Beta2.jar org.picketbox.datasource.security.SecureIdentityLoginModule senha

  Encoded password: -21fe4fcab9086fdc

Agora edite o arquivo:

  vim jboss-as-7.1.0.CR1/standalone/configuration/standalone.xml

Encontre o Subsystem  “<subsystem xmlns=”urn:jboss:domain:security:1.0″>” e entre as tags <security-domains>
Insira o conteúdo abaixo.

<security-domain name="security-encrypted-ds" cache-type="default">
  <authentication>
     <login-module code="org.picketbox.datasource.security.SecureIdentityLoginModule" flag="required">
      <module-option name="username" value="usuario_database"/>
      <module-option name="password" value="-21fe4fcab9086fdc"/>
      <module-option name="managedConnectionFactoryName" value="jboss.jca:service=LocalTxCM,name=MyPool"/>
      </login-module>
   </authentication>
</security-domain>

Edite novamente o “Subsystem” <subsystem xmlns=”urn:jboss:domain:datasources:1.0″>, dentro da tag  <security> :

Remova:

  <user-name>usuario_database</user-name>
  <password>senha_database</password>

E adicione o dominio de segurança que acabamos de configurar:

  <security-domain>security-encrypted-ds</security-domain>

Pronto 🙂 , o nosso data source está funcionando com a senha encriptada, agora vamos criar um domínio de segurança, que utiliza o data source encriptado e armazena os roles e users em tabelas.

Vamos gerar a senha encriptada do usuário que irá acessar o nosso domínio de segurança, para isso crie uma classe Java, utilizando a estrutura abaixo:

As libs utilizadas são: modules/org/jboss/logging/main/jboss-logging-3.1.0.CR2.jar
                                             modules/org/picketbox/main/picketbox-4.0.6.Beta2.jar

import org.jboss.security.auth.spi.Util;

public class Main {

public static Util util;

public static void main(String[] args) {
    System.out.println(util.createPasswordHash("SHA-256", "BASE64", null, null, "senha"));
  }
}

Retorno: t+lL5RPpboxFzSPRYideWhLr3pEApCXE683X+k3NiXw=

Crie as tabelas abaixo no db_security:

create table users (username varchar(32) not null primary key,password varchar(100) not null);
create table roles (username varchar(32) not null,rolename varchar(32) not null,primary key (username, rolename));
insert into users (username, password) values ("usuario", "t+lL5RPpboxFzSPRYideWhLr3pEApCXE683X+k3NiXw=");
insert into roles values ("usuario", "Admin");

Novamente no Subsystem  “<subsystem xmlns=”urn:jboss:domain:security:1.0″>” e entre as tags <security-domains>

Insira o conteúdo abaixo:

<security-domain name="security-database" cache-type="default">
 <authentication>
   <login-module code="Database" flag="required">
      <module-option name="dsJndiName" value="java:/MySQLDS"/>
      <module-option name="principalsQuery" value="select password from users where username=?"/>
      <module-option name="rolesQuery" value="select rolename, 'Roles' from roles where username=?"/>
      <module-option name="hashAlgorithm" value="SHA-256"/>
      <module-option name="hashEncoding" value="base64"/>
   </login-module>
 </authentication>
</security-domain>

Agora na aplicação Web, adicione o conteúdo abaixo no web.xml

<security-constraint>
 <web-resource-collection>
   <web-resource-name>HtmlAuth</web-resource-name>
   <description>Test Security Domains</description>
   <url-pattern>/*</url-pattern>
   <http-method>GET</http-method>
   <http-method>POST</http-method>
 </web-resource-collection>
 <auth-constraint>
   <role-name>Admin</role-name>
 </auth-constraint>
</security-constraint>
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>My Test JBoss AS 7</realm-name>
</login-config>
<security-role>
  <role-name>Admin</role-name>
</security-role>

Crie o arquivo jboss-web.xml, e adicione o conteúdo abaixo:

<jboss-web>
<security-domain>java:/jaas/security-database</security-domain>
</jboss-web>

Realize o deploy e acesse pelo browser  de sua preferência, a aplicação deverá pedir o usuário e senha que estão armazenados no banco de dados.

Vou deixar os principais arquivos utilizado nesse post aqui para download.
Link:  Arquivos
Abraços a todos

🙂

22 comentários em “Introdução ao JBoss AS 7.1 – Parte 2

    Jorge Guedes disse:
    23 de janeiro de 2012 às 15:34

    Mocokinha…. isso ai.. mais um post… parabens

    celmo disse:
    24 de janeiro de 2012 às 15:52

    Estou tentando executar o comando: java -cp modules/org/jboss/logging/main/jboss-logging-3.1.0.CR2.jar:modules/org/picketbox/main/picketbox-4.0.6.Beta2.jar org.picketbox.datasource.security.SecureIdentityLoginModule minhasenha, e estou recebendo a seguinte mendagem de erro “Erro: Nao foi possivel localizar nem carregar a classe principal org.picketbox.datasource.security.SecureIdentityLoginModule”

      Mauricio Magnani respondido:
      24 de janeiro de 2012 às 21:25

      Olá Celmo, isso é bem simples, verifique se os JARs desse comando estão realmente no JBoss AS e os caminhos estão corretos,vai na linha de comando no linux e faz o comando passo a passo e vai dando tab que ele vai completando. Nesse post estou utilizando a versão jboss-as-7.1.0.CR1.
      Qualquer coisa posta ai novamente 🙂
      abraços!

        Joao Godoy disse:
        3 de julho de 2012 às 16:51

        Boa tarde, estou tendo o mesmo problema que o Celmo, os caminhos estão corretos, verifiquei todos, até mesmo dentro do picketbox-4.0.6.Beta2.jar se exisita a classe SecureIdentityLoginModule.
        Estou usando windows 7, java 1.7.0_05 e jboss.7.1.0.CR1B.

    […] dominio de segurança encriptado para os dados de acesso ao banco de dados, para isso vejam o Post Introdução ao JBoss AS parte 2 […]

    Mauricio Magnani respondido:
    3 de julho de 2012 às 17:00

    Olá João eu testei novamente com a versão JBoss EAP 6 (JBoss AS 7) e Funcionou veja abaixo:

    [mmagnani@mmagnani jboss-eap-6.0]$ java -cp modules/org/jboss/logging/main/jboss-logging-3.1.1.GA-redhat-1.jar:modules/org/picketbox/main/picketbox-4.0.9.Final-redhat-1.jar org.picketbox.datasource.security.SecureIdentityLoginModule senha
    Encoded password: -21fe4fcab9086fdc

    Eu penso que esse erro esteja relacionado ao seu classpath do seu JDK… Veja abaixo:

    http://www.coderanch.com/t/552660/java/java/Java-Could-not-find-or

    Verifique se o seu JDK está funcionando corretamente pelo console…

    http://www.dicasquefunfa.com.br/2011/09/java-variavel-de-ambiente-no-windows.html

    Qualquer coisa posta ai…

    Abraços

    Mauricio Magnani respondido:
    3 de julho de 2012 às 17:02

    Um post em Ingles similar a esse veja: http://middlewaremagic.com/jboss/?p=2193

    []s

      Joao Godoy disse:
      12 de julho de 2012 às 9:34

      Ola de novo! Desculpe a demora em dar um retorno.
      Descobri o erro, o meu class_path e path já estavam corretos, o comando está usando dois pontos “:”, o correto é usar ponto e virgula “;”. Não sei se isso é diferente entre o linux e o windows. Bastou trocar isso que o comando executou e gerou o password!

        Joao Godoy disse:
        12 de julho de 2012 às 15:19

        Só acrescentando,
        Alem de trocar o dois ponto, ‘:’, por ponto e virgula, ‘;’, tambem troquei o ‘/’ por ‘\’.
        Estou usando windows 7, java 1.7.0_05 e jboss.7.1.0.CR1B.

        Obrigado pela ajuda.

    Mauricio Magnani respondido:
    12 de julho de 2012 às 15:38

    Vlw Joao Muito Bom agora ficou documentado se alguem tiver esse problema já sabe como resolver 🙂

    Eu testei somente no Linux 😀

    Vlw Abraços

    Luis disse:
    26 de novembro de 2012 às 13:56

    Estou com a versão 7.1.1 Final, e está dando erro ao inserir o elemento “security-domain” no standalone.xml, conforme segue abaixo:

    13:52:09,036 ERROR [org.jboss.as.server] JBAS015956: Caught exception during boot: org.jboss.as.controller.persistence.ConfigurationPersistenceException: JBAS014676: Failed to parse configuration
    at org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:141) [jboss-as-controller-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.server.ServerService.boot(ServerService.java:266) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.controller.AbstractControllerService$1.run(AbstractControllerService.java:155) [jboss-as-controller-7.1.1.Final.jar:7.1.1.Final]
    at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_05]
    Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[479,4]
    Message: JBAS014789: Unexpected element ‘{urn:jboss:domain:security:1.1}security-domain’ encountered
    at org.jboss.as.controller.parsing.ParseUtils.unexpectedElement(ParseUtils.java:85) [jboss-as-controller-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.security.SecuritySubsystemParser.readElement(SecuritySubsystemParser.java:133) [jboss-as-security-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.security.SecuritySubsystemParser.readElement(SecuritySubsystemParser.java:63) [jboss-as-security-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.staxmapper.XMLMapperImpl.processNested(XMLMapperImpl.java:110) [staxmapper-1.1.0.Final.jar:1.1.0.Final]
    at org.jboss.staxmapper.XMLExtendedStreamReaderImpl.handleAny(XMLExtendedStreamReaderImpl.java:69) [staxmapper-1.1.0.Final.jar:1.1.0.Final]
    at org.jboss.as.server.parsing.StandaloneXml.parseServerProfile(StandaloneXml.java:894) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.server.parsing.StandaloneXml.readServerElement_1_1(StandaloneXml.java:330) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.server.parsing.StandaloneXml.readElement(StandaloneXml.java:127) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.server.parsing.StandaloneXml.readElement(StandaloneXml.java:100) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.staxmapper.XMLMapperImpl.processNested(XMLMapperImpl.java:110) [staxmapper-1.1.0.Final.jar:1.1.0.Final]
    at org.jboss.staxmapper.XMLMapperImpl.parseDocument(XMLMapperImpl.java:69) [staxmapper-1.1.0.Final.jar:1.1.0.Final]
    at org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:133) [jboss-as-controller-7.1.1.Final.jar:7.1.1.Final]
    … 3 more

    Obrigado!

      Mauricio Magnani Jr respondido:
      26 de novembro de 2012 às 14:08

      Post o seu standalone.xml no paste bin e ma passa o link para eu dar uma olhada 🙂

      http://pastebin.com/

      Ps: O wordpress nao deixa postar xml nos comentários :/

      Vlw

        Luis disse:
        26 de novembro de 2012 às 15:19

        Segue o link: http://pastebin.com/TK2qijhD

        Obrigado pela agilidade em responder, Maurício!

        Mauricio Magnani Jr respondido:
        26 de novembro de 2012 às 15:36

        Rlxa Man é nóis…

        Seguinte vc fechou a tag

        de depois disso declarou

        hehe

        é um erro simples mas quando estamos tão focados nao conseguimos enxergar rsrs

        Abs

        Mauricio Magnani Jr respondido:
        26 de novembro de 2012 às 15:38

        rsrs esse xml me mata kkk vc fecheou security-domains e depois declarou security-domain name=”security-encrypted-ds” 😀

    Luis disse:
    26 de novembro de 2012 às 16:58

    cara, desculpa a falha aí e também obrigado por me ajudar com este erro de aspira.. hehe

    aproveitando a oportunidade, vc sabe me dizer se tem como definir os Roles de modo dinâmico (retornados via banco) ou se os mesmos devem estar “estaticamente” mencionados no arquivo web.xml? Ainda, fiz uma implementação do LoginModule e entre os métodos temos o commit() que retorna um boolean. Nele, eu somente consegui atribuir as roles ao usuário logado adicionando antes ao um grupo e o grupo depois sendo adicionado ao Subject.
    Você chegou a implementar um LoginModule customizado que chega demais permissões, criptografia de senhas etc?

    Abraços!

      Mauricio Magnani Jr respondido:
      27 de novembro de 2012 às 0:01

      Hehe dia boa 🙂 Desculpe a demora em responder o dia foi muito corrido. Cara quando eu trabalhava no suporte
      da Red Hat minha “especialidade” era justamente essa Security e realmente só vi até hoje roles definidas estaticamente no web.xml… JavaEE 5.
      eu acredito que no JavaEE 6 possa fazer algo dinâmicos utilizando anotações 😀 mas tenho que dar uma pesquisada.

      Ná época não cheguei a criar mas deu suporte em um login module customizado de um grande cliente LATAM e tinha tudo de mais avanaçado que se possa
      imaginar em segurança… fiquei até com inveja rsrs Acredito que se der uma pesquisada na doc consiga além do que vc implementou.

      Dá uma olhada no PicketLink ele é uma excelente alternativa no ambiente JBoss.

      Abs

        Luis disse:
        27 de novembro de 2012 às 11:29

        Vou dar uma olhada no picketlink, cara.. valeu!!

        Uma outra coisa sobre questão de segurança que tenho que implementar aqui é sobre a definição de um outro nível de permissão. Além do usuário pertencer a determinado grupo (admin, user etc), antes ainda é preciso especificar a quais sistemas ele têm acesso. Quero elaborar uma página que contenha um menu do Primefaces, por exemplo, que possa ser “construído” dinamicamente contendo itens para cada um dos sistemas que o usuário tenha acesso. Ao clicar em um item, é aberto seu respectivo sistema (um novo projeto JSF para cada um).
        É possível fazer algo desse tipo usando a estrutura padrão do JAAS, ou seja, além de definir os tipos de papéis permitidos para o usuário, também especificar itens mais específicos que ele tenha acesso, como sistemas e ainda operações sobre aquela tela que ele está visualizando (leitura, escrita)?

        Obrigado mais uma vez!

        Mauricio Magnani Jr respondido:
        28 de novembro de 2012 às 14:17

        Oi Luis desculpe a demora em responder…
        Sim é possível fazer o que vc quer por que eu mesmo já vi um sistema do TRE em algum orgão do nordeste que funciona dessa forma o problema é que eu mesmo nunca desenvolvi algo similar. Mas dá sim só temos que pensar como rsrs

        Desculpa não poder ajudar mais… se eu tiver alguma idéia de como pode ser feito isso posto aqui..

        Abraços

    Rodrigo disse:
    7 de dezembro de 2012 às 0:21

    Oi Mauricio, tranquilo?

    Gostaria de tirar uma dúvida:

    Ao fazer a query para pegar as role do usuário, eu posso selecionar mais de uma role?

    Por exemplo:

    Nesse exemplo que você mostrou, temos a rolesQuery “select rolename, ‘Roles’ from roles where username=?”. Legal, até ai tudo bem, testei e isso worka legal no meu projeto para um usuario com um perfil só (uma unica role).

    Entretanto, visando uma atualização futura no meu sistema, queria deixá-lo apto a usuarios com muitas roles:

    Queria saber caso eu use uma query parecida com essa abaixo (que atenderia minha necessidade) para pegar muitas roles de um usuário funciona:

    “select p.perfil, ‘Roles’ from usuario as u
    inner join usuario_perfil as up on up.id_usuario = u.id
    inner join perfil as p on p.id = up.id_perfil
    where u.usuario=?”

      Mauricio Magnani Jr respondido:
      7 de dezembro de 2012 às 1:09

      Oi Rodrigo tudo bom sim vlw 🙂

      Verificando aqui a sua query acredito que funcionaria. Já realizou alguns testes?
      Que tal testar e me dizer o resultado?! 😀

      Ai nós já ajudariámos outras pessoas que passarem por isso… mas se der algum problema me diz ai que vamos resolver.

      Abs

Deixe um comentário