mar 19

Adicionando um certificado e uma chave em um keystore para configurar HTTPS no JBOSS

Estava eu tentando configurar o ssl no JBOSS 7.1 Community para utilizar meu certificado obtido no StartSSL e me deparei com o seguinte problema : 2 Arquivos um com extensão .crt e outro com extensão .key . Quando você olha os tutoriais de como configurar o ssl no jboss todos vão ensinar a criar um certificado fake e colocar no keystore, mas o que eu precisava era adicionar uma certificado de verdade.

Depois de algum tempo procurando eu encontrei a solução, são necessários 2 passos que é a transformação dos 2 arquivos .crt e .key em um arquivo do tipo pkcs12 que tem a extensão .p12 , e em seguida você deve importar esse certificado criado para um keystore java qualquer que você tenha.

Você precisará de 2 ferramentas: o OpenSSL , nativo no linux e para windows você acha aqui  e o Keytool do próprio java , basta ter alguma versão do java instalado para usá-lo, aqui tem uma referência legal dos principais comandos.

Agora vamos aos comandos necessários

Comando 1:

openssl pkcs12 -export -name [nome-do-certificado] -in [certificado.crt]  -inkey [chave-certificado.key]  -out keystore
.p12

Comando 2:

 keytool  -importkeystore -destkeystore [keystore-java-criado.jks]-srck
eystore keystore.p12 -srcstoretype pkcs12 -alias [alias-desejado]

E pronto, agora você poderá configurar um connector do jboss para utilizar ssl, utilizando seu certificado digital e poder utilizar https em suas aplicações.

<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false"> 

  <connector name="https" scheme="https" protocol="HTTP/1.1" socket-binding="https" enable-lookups="false" secure="true">

    <ssl name="foo-ssl" password="secret" protocol="TLSv1" key-alias="[alias-desejado]" certificate-key-file="[keystore-java-criado]" />

  </connector>

</subsystem>

E é isso!

 

out 28

Mais uma dica para chromecast

Acabei de achar mais um aplicativo para utilizar com o chromecast, é o popcorn time ! Não se assustem com o link, pois como o popcorn time é um projeto open source, há mais de um em desenvolvimento e o do site https://popcorntime.io/ é o aplicativo melhorzinho, porém esse do  http://popcorn-time.se/ é o que tem suporte a chromecast, e pelo que eu pude testar até agora está rodando lisinho.

Só tem um porém, as legendas das séries a princípio não tem nesse popcorn time, mas você pode baixar a legenda e colocar que funciona sem problemas!

Fica a dica!

 

ago 27

Usos para o chromecast

Há dois meses comprei um chromecast e mesmo tendo smartv vale a pena!

Ele sozinho não faz muita coisa, mas em conjunto com um smartphone ou tablet e um pc para ser o media server as possibilidades são muitas!!  Nesse post vou resumir algumas que eu utilizo.

  1. Netflix – mesmo minha TV tendo Netflix, utilizar do celular e mandar para o chromecast é muito mais rápido, fora isso não tem muita vantagem.
  2. Youtube – mesmo caso do Netflix, transmitir pelo chromecast é muito mais rápido, principalmente porque navegar nos aplicativos da TV via controle remoto é uma porcaria. Tem até aplicativo de controle remoto para o celular, mas não é muito bom também.
  3. Rdio – vai receber gente em casa e quer colocar aquela música ambiente, baixe o Rdio(Google play store ou apple store), e manda pro chromecast. Fica melhor ainda se você tiver um home theater!
  4. Plex – Esse é pra mim o melhor uso de todos.O Plex é um media server onde você instala ele em algum PC, configura seus diretórios de filmes, seriados, shows, etc. e você pode configurar para ele baixar sinopses, capa, informações, legendas além dele organizar seus seriados por temporada!  Você pode também comprar o app do plex (Android, Iphone) para controlar o que quer ver, ou está vendo a partir do tablet ou smartphone!
  5. Videostream – plugin para o google chrome onde você pode escolher um arquivo no seu pc, escolher o arquivo de legenda e mandar tocar no chromecast. Ele também tem um app, por enquanto só para Android e em breve para Iphone, onde uma vez iniciado o filme a partir do seu pc, ele passa a controlar pause e avançar ou voltar o filme.

Esses são meus principais usos do chromecast até o momento, ainda acredito que vários apps farão uso do chromecast, aumentando ainda mais sua utilidade. Eu comprei por 120 reais, mas até mesmo os 200 reais que são cobrados aqui valem a pena.

ago 06

Habilitar log de aplicação no JBOSS EAP 6.1

Pra quem utiliza essa versão do jboss e se não me engano toda a linha EAP funciona desta maneira já deve ter reparado que ao tentar logar utilizando log4j nada aparece no console.

Para resolver isso basta adicionar o argumento de VM -Dorg.jboss.as.logging.per-deployment=false no arquivo standalone.conf ou se você está no eclipse basta dar 2 cliques no servidor jboss que irá aparecer uma aba com dados do servidor, em seguida selecione a opção Open launch configuration e irá aparecer a caixa de texto contedo todos os argumentos de VM, basta adicionar no final.

mai 21

Loading gifs

Dica rápida para quem trabalha com ajax e não sabe criar ou manipular imagens e não quer perder tempo caçando imagens prontas na internet.

Quando queremos bloquear a tela e mostrar que estamos executando um processamento ajax que demora alguns segundos ou até minutos,é interessante colocar uma imagem animada que indique ao usuário que algo está sendo executado. Para criar esses gifs eu encontrei nas internets um site bem legal : http://preloaders.net/ .

Nele você tem uma lista de gifs( não são muitos, mas já ajuda), e aí você pode personalizar cor, velocidade, frames, dentre outras características do gif e criar na mesma hora do jeito que você quiser!

mai 06

Jquery com JSF

Quem trabalha com JSF com certeza já viu os ids dos elementos html gerados por ele da seguinte maneira  form:idElementoPai:idElemento . Mesmo usando a propriedade prependId = false da tag h:form alguns elementos aninhados ganham o id do pai.

Se você usa javascript puro para buscar os elementos pelo id utilizando document.getElementById(“form:idElementoPai:idElemento”) não temos problema algum, tudo funciona! Porém quando utilizamos jquery , a seleção de um elemento por id $(‘#form:idElementoPai:idElemento’)  simplesmente não funciona, e muitas vezes adotei a alternativa de buscar pelo seletor de classe, me obrigando a adicionar classes css únicas(mas não é necessário defini-las em um arquivo css, basta declarar no elemento).

Porém é possível sim utilizar o seletor do Jquery nesses casos desses ids compostos, bastando adicionar o \\ antes do caracter :(dois pontos)  ficando da seguinte maneira:

$('#form\:idElementoPai\:idElemento')

mai 03

Equals com Objeto do tipo proxy do hibernate

Há tempos que não posto nada, estou devendo muita coisa. Mas essa aqui eu tava me ferrando e acho que vale a pena registrar.

A situação é a seguinte: Tenho uma entidade A que se relaciona com a entidade B  em um relacionamento OneToOne, porém não quero utilizar o carregamento eager padrão para este relacionamento. Para resolver isso base adicionar a propriedade fetch=FetchType.LAZY na anotação OneToOne.  Mas como dizia Joseph Climber, a vida é uma caixinha de surpresas. Não é que pra minha surpresa o cache do hibernate resolveu funcionar em um select e manteve um objeto do tipo B que eu já tinha carregado a partir de um do tipo  A. Ou seja, no meio da listagens de objetos do tipo retornados do meu select * , tinha um intruso do tipo lazy do hibernate no meio da listagem WTF???!! . Ou seja, meu equals (gerado pelo eclipse) estava executando a instrução if (getClass() != obj.getClass()) e retornando true, uma vez que aquele bendito objeto lazy intruso não era da mesma classe!!

Agora chega de blablabla e vamos pras soluções:

Solução 1:

Devemos adicionar a seguinte verificação:

Onde tínhamos:  if (getClass() != obj.getClass())

Devemos ter agora:

Class<?> objProxyClass = 
HibernateProxyHelper.getClassWithoutInitializingProxy(obj);
 if (getClass() != obj.getClass() && getClass()!= objProxyClass )

e voi là , na chamada ao método getClassWithoutInitializingproxy é retornada a classe original do meu proxy e o if seguinte funciona sem problema algum!

Solução 2:

Essa solução foi retirada da documentação do hibernate

 if( !(obj instanceof B)) return false;

Essa é bem mais simples e também funciona!!

Agora fica a seu critério a utilização de uma ou de outra.

Lembrando que toda vez que seu objeto tiver a possibilidade de ser um proxy do hibernate nunca utilize diretamente os atributos no equals, faça as comparações sempre utilizando os métodos GETTERS!!!

É isso, se alguém souber uma situação que uma solução ou outra não atenda pode comentar aí, até a próxima.

set 05

Mapeando chaves compostas com JPA 2

Muitas vezes utilizamos em nossas tabelas chaves compostas para identificação de uma tupla, um exemplo seria na tabela empregado a chave primária ser composta pelos atributos cpf e matrícula do empregado, vocês podem dizer que bastaria o cpf ou a matrícula para identificar o empregado, mas aqui estou apenas exemplificando para mostrar como mapeamos esta chave composta utilizando JPA2.

Para isso a JPA nos oferece 2 estratégias de mapeamento:

  • IdClass
  • EmbeddedId

Eu até o momento ainda não identifiquei uma diferença de desempenho entre as duas estratégias, nem vejo vantagem em questão de verbosidade de uma em relação a outra, portanto mostrarei as 2 e quem quiser escolhe a que melhor convir.

Utilizando IdClass 

Para se utilizar de idClass precisamos criar uma classe com os atributos que compõem nossa chave primária da seguinte maneira:

public class EmpregadoId {

private String cpf;
private String matricula;

//getters e setters
@Override
public int hashCode() {
//código hashcode
}

@Override
public boolean equals(Object obj) {
//código equals
}
}

Devemos sempre implementar os métodos hashcode e equals da nossa classe de Id, o hibernate apenas dará um alerta caso não estejam implementados estes métodos.

Agora na nossa classe de entidade devemos ter o seguinte código:

@Entity
@IdClass(EmpregadoId.class)
public class Empregado {

@Id
private String cpf;

@Id
private String matricula;

//Outros atributos e getters e setters

Ou seja, basta anotar com @IdClass a classe de entidade, passando por parâmetro a classe que contém os atributos do id, e devemos anotar com @Id os atributos que compõem o id, que são os mesmos da classe de id.

E é só, nessa estratégia a classe que representa o id não precisa de anotações, e não será utilizada pela nossa aplicação, porém é necessária para que a estratégia funcione.

 

Utilizando EmbeddedId

Nesta  estratégia também precisamos de uma classe com os atributos da chave primária, porém esta classe deve ser anotada como @Embeddable e deve obrigatoriamente implementar a interface Serializable , além de implementar os métodos hashcode e equals assim como na estratégia anterior. Assim temos a classe de id da seguinte maneira:

@Embeddable
public class EmpregadoId implements Serializable {

private static final long serialVersionUID = 1L;
private String cpf;
private String matricula;

//getters e setters
@Override
public int hashCode() {
//código hashcode
}

@Override
public boolean equals(Object obj) {
//código equals
}
}

Já a nossa entidade ficará da seguinte maneira:

@Entity
public class Empregado {

@EmbeddedId
private EmpregadoId id;

//Outros atributos e getters e setters

Ou seja, agora para acessar os atributos da chave primária composta devemos buscar através do atributo id que será do tipo EmpregadoId, que é anotado com @EmbeddedId  .

_____________________________________________________________________________________

Vimos então como é simples mapear chaves primárias compostas utilizando JPA 2, o único problema é que sempre precisamos de uma classe auxiliar que possuirá os atributos que compõem a chave.

fev 19

Autenticação com Apache Shiro e JSF

Nesse post vou mostrar uma soluçao que eu adotei para integrar o JSF e JPA com o Shiro, não digo que seja a melhor ou a mais prática, mas é uma solução.

Primeiramente o que é Shiro?

Segundo o próprio site do Shiro :

“Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.”

Ou seja, é um framework Java de segurança.

Este post cobre apenas a parte de autenticação. Vamos ao que interessa então:

1) Adicionar as dependências

Para quem usa Maven :

 
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-core</artifactId>
   <version>1.2.1</version>
</dependency>
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-web</artifactId>
   <version>1.2.1</version>
</dependency>

Essa era a versão mais recente na época do post! Caso queira se certificar disso acesse http://mvnrepository.com/ e busque por Shiro.

2) Configurar o web.xml

Você precisará registrar o filtro do Shiro para filtrar suas requisições e um listener.

 
<listener>
   <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
   <filter-name>ShiroFilter</filter-name>
   <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>

<filter-mapping>
   <filter-name>ShiroFilter</filter-name>
   <url-pattern>/*</url-pattern>
   <dispatcher>REQUEST</dispatcher>
   <dispatcher>FORWARD</dispatcher>
   <dispatcher>INCLUDE</dispatcher>
   <dispatcher>ERROR</dispatcher>
</filter-mapping>

 

3) Criar o arquivo shiro.ini na pasta WEB-INF onde está o web.xml

Você pode colocar esse arquivo em outro lugar , mas aí você precisará indicar isso no web.xml . Vamos adotar aqui a política “convenção sobre configuração”.

Este arquivo contém a configuração necessária para que o Shiro funcione.

Se você procurar no google achará diversas maneiras de configurá-lo. Aqui estamos bem básicos:

[main]

meurealm = meupacote.MeuRealm
securityManager.realms = $meurealm
authc.loginUrl=/login.xhtml
[users]
[roles]

[urls]
# enable authc filter for all application pages
/login.xhtml = authc
/secure/** = authc

 

Neste arquivo eu configurei o meu realm autenticador. Se quiser saber mais sobre realms leia http://shiro.apache.org/realm.html .

Em seguida atribuo aos realms do securityManager. Posso ter quantos realms eu quiser.
authc.loginUrl=/login.xhtml serve para indicar minah url de autenticação.
[users]
[roles]
Não são necessários aqui pois estou guardando-os no banco de dados.
Em [urls] eu declaro quais urls precisam de autenticação. Caso eu tenha páginas públicas basta fazer o seguinte:
/public/** = anom
Ou seja, todas as páginas embaixo do diretório public não necessitam de autenticação.
Em /secure/** = authc só será permitido o acesso a essas páginas caso haja usuário logado, essa verificação fica transparente para o desenvolvedor, uma vez que o filtro do shiro declarado no web.xml fará este trabalho.

 

4) Implementar o Realm autenticador

 
public class MeuRealm implements Realm {

@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
    throws AuthenticationException {
        String principal = (String) token.getPrincipal();

        MeuDAO dao = new MeuDAO();
        String credencial = dao.buscarCredencial(principal);

        if(credencial != null) {
             AuthenticationInfo info = new SimpleAuthenticationInfo(principal,credencial,getName());
             SimpleCredentialsMatcher cmatcher = new SimpleCredentialsMatcher();

             boolean credentialsMatch = cmatcher.doCredentialsMatch(token, info);
             if(credentialsMatch) {
                 return info;
             }

         }
         throw new AuthenticationException();

}

@Override
public String getName() {

return "MeuApp";
}

@Override
public boolean supports(AuthenticationToken token) {
   //valido o token 
     ...
   //tudo ok com ele
    return true;  
   //problema com o token
    return false;

}

 

Neste código eu implemento a interface Realm e nela eu preciso implementar os 3 métodos mostrados acima. Quando esta classe será chamada eu mostrarei mais pra frente.

Mas basicamente o que é preciso saber é o seguinte:

No método supports eu recebo um token e preciso verificar se este token é válido para meu realm, como só temos um tipo de autenticação posso retornar true direto.
No método getName deve-se retornar um nome único para esse Realm.

Já no método getAuthenticationInfo é onde temos que colocar a mão na massa. Segundo a documentação do Shiro deve-se implementá-lo da seguinte maneira, primeiro você verifica se existe o usuário contido no Principal do seu token e retorna a credencial dele. No meu caso eu retorno null caso não ache nenhum usuário, caso ache eu retorno a senha do usuário.
Em seguida você deve criar um CredentialMatcher para verificar se a credencial do token é válida, neste exemplo eu fiz a verificação mais simples que é a de igualdade.
Caso você utilize conexão segura e sua senha seja recebida em texto claro e você armazene-a em formato de hash SHA256, você pode utilizar o Sha256CredentialsMatcher por exemplo.
Caso a verificação das credenciais retorne true você deve retornar um novo objeto AuthenticationInfo. Caso não o ache a documentação diz para se retornar null, mas você pode fazer do jeito que quiser.

5) O ManagedBean de login

Aqui é bem simples também, primeiramente eu instancio um UsernamePasswordToken passando o usuário e senha digitados no formulário.
Em seguida eu busco o Subject, que é o conceito de usuário que o Shiro utiliza, através do método estático SecurityUtils.getSubject().
Por fim eu chamo o método login do Subject criado passando o token gerado.
Ao fazer isso o Shiro vai invocar o(s) Realm(s) criado(s) que você declarou no shiro.ini , e chamar o método supports, caso retorne true ele chamará o getAuthenticationInfo.
Caso este último retorne um objeto do tipo AuthenticationInfo ele irá prosseguir na execução, no meu caso redirecionando o usuário para a área restrita da aplicação.
Se retornar uma AuthenticationException, eu adiciono uma mensagem genérica no FacesContext de que o usuário é inválido.

 
public void login() throws IOException {
        FacesContext ctx = FacesContext.getCurrentInstance();
        UsernamePasswordToken token = new UsernamePasswordToken(
                usuario.getEmail(), usuario.getSenha());
        Subject currentUser = SecurityUtils.getSubject();
        try {
            currentUser.login(token);
            ctx.getExternalContext().redirect("secure/index.xhtml");
        } catch (AuthenticationException ae) {

            ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Usuário/senha inválido(s)!", "Usuário/senha inválido(s)!"));
        }

    }

 

6) Todo login precisa de um logout

Por fim para deslogar o usuário basta o seguinte

 
Subject currentUser = SecurityUtils.getSubject();
currentUser.logout();

Recomendo também redirecionar o usuário, pois não é feita a validação caso você esteja utilizando ajax.

 

Bom, é isso, sei que ficou um pouco confuso, mas eu tentei resumir ao máximo este assunto, uma vez que ele é bem mais complexo do que o que foi apresentado aqui. Pra quem for utilizar produtivamente  recomento a leitura da documentação antes.

fev 05

Dica rápida de compras na china

Acabei de receber minha segunda encomenda ontem. Comprei no fim do ano passado um headphone bluetooth e um capa pra kindle! O lugar? Aliexpress . Todas as compras vieram com rastreio, aí é só colocar lá no muambator e receber por email as notificações de mudança.

Antes eu comprava no DX, mas estava vindo sem rastreio e algumas das minhas encomendas não estavam chegando, aí é só dor de cabeça reclamando lá.  No Aliexpress não tem erro, 2 dias depois da compra é postado o produto e você recebe o código de rastreio. E se não chegar você abre uma disputa no site para reaver seu dinheiro. Não precisei disso ainda, e espero não precisar, mas já é uma medida de confiança a mais!

É isso pra quem comprava no DX e está achando o serviço deles ruim fica a dica!