Behavior Driven Development _pt_BR.properties

November 25th, 2009 agnaldo4j No comments

Olá,

Estudando Ruby nestes últimos dias, assisti um screencast que falava sobre o uso de Behavior Driven Development, para criar os testes de uma aplicação escrita em ruby, este screencast fala dos frameworks RSpec e cucumber e  é um ótimo início para quem quer usar este modo de testar suas aplicações.

Eu já tinha escutado sobre Behavior Driven Development antes, porém nunca tinha dado a devida atenção,  então como vi e ouvi mais uma vez que o Behavior Driven Development realmente me servia, inicieai as buscas por uma versão de RSpec ou cucumber para Java, de forma que eu fizesse meus testes da mesma forma, então descobri o JBehave.

Quando assisti este screencast eu estava procurando uma forma de testar o framework web que estou desenvolvendo, isso me mostrou um caminho interessante de como fazer estes testes de uma forma mais clara, que me guiasse pelas funcionalidades que eu espero ter e não me perder em coisas não tão importantes, mantendo o objetivo enquanto escrevo meu software, também queria que estes testes  servissem como documentação tanto para outros desenvolvedores como para pessoas não ligadas diretamente ao desenvolvimento, de forma a ter uma documentação viva, os cenários são isso.

Para tornar a comunicação destes cenários mais forte, decidi usar o JBehave escrevendo cenários em portugês, então iniciei meus estudos que acabaram gerando este projeto BDD_estudos usando a IDE Eclipse.

Este é o cenário de exemplo que foi base para todo o desenvolvimento do projeto BDD_estudos.

Dado que eu nao estou logado
Quando eu logar como Agnaldo e com a senha teste
Entao eu queria ver a mansagem "Bem-vindo, Agnaldo!"

Este assunto ainda não acabou, pois agora vem a parte mais interessante, realmente usar Behavior Driven Development para fazer os testes do framework web que estou desenvolvendo, mas isso fica para uma próxima.

Valeu, até.

Categories: Agile, Java, Ruby Tags:

A hístoria da agilidade

November 12th, 2009 agnaldo4j No comments

Entendendo de onde vem os princípios ágeis tão falados hoje em dia.

Tão importante quanto seguir uma metodologia é conhecer sua filosofia.

Categories: Agile Tags: , , ,

Reforçando a comunicação e o comprometimento com Kanban

November 12th, 2009 agnaldo4j No comments

Há duas semanas tivemos que trabalhar em um desenvolvimento, daqueles que todo desenvolvedor sonha. :-)

1. Pouco tempo para desenvolvimento.

2. Negócio complicado.

3. Cliente aguardando para homologação deste e de outros itens(Não podiamos quebrar o build pois atrasaria a homologação).

Inicialmente pensamos que com 8 dias para desenvolver, criar testes e garantir qualidade , seria inevitável trabalhar no final de semana, já que haviam várias tarefas encontradas em uma análise superficial e ainda tinhamos algumas analises por fazer.

Para organizarmos estas tarefas, decidimos usar um kanban.

quadro de atividades

quadro de atividades

Usando essa ferramenta conseguimos manter uma boa comunicação, foco na solução dos problemas, entrega com testes e garantia de qualidade.

Se você tem dúvidas do que é o kanban dê uma olhada nesta apresentação.

Categories: Agile Tags: , , , ,

Assinando documentos xml

November 12th, 2009 agnaldo4j 2 comments

Continuando com o assunto de criptografia, vou passar um modelo de como fazer assinatura de documentos xml(Nota Fiscal Eletrônica), para isso vou usar a classe mostrada no post anterior.

Código:

package com.softsimples.crypto;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class AssinadorDeXML  {
	private XMLSignatureFactory signatureFactory;
	private DigestMethod digestMethod;
	private Transform transform;
	private Transform c14NTransform;
	private List<Transform> listOfTransforms;
	private final String c14NTransformStr = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
	private final GerenciadorDeKeystore gerenciadorDeKeystore;

	public AssinadorDeXML(GerenciadorDeKeystore gerenciadorDeKeystore) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, InvalidAlgorithmParameterException {
		this.gerenciadorDeKeystore = gerenciadorDeKeystore;
		this.listOfTransforms = new ArrayList<Transform>();
		this.signatureFactory = XMLSignatureFactory.getInstance("DOM");
		this.digestMethod = this.signatureFactory.newDigestMethod(DigestMethod.SHA1, null);
		this.transform = this.signatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec)null);
		this.c14NTransform = this.signatureFactory.newTransform(c14NTransformStr, (TransformParameterSpec)null);
		this.listOfTransforms.add(this.transform);
		this.listOfTransforms.add(this.c14NTransform);
	}

	public void criarAssinaturaParaXML(Document document, String strReference) throws KeyStoreException, SAXException, IOException, ParserConfigurationException, UnrecoverableKeyException, NoSuchAlgorithmException, MarshalException, XMLSignatureException, TransformerException, InvalidAlgorithmParameterException {
		Reference reference = this.signatureFactory.newReference(strReference, digestMethod, this.listOfTransforms,null, null);
		CanonicalizationMethod canonicalizationMethod = this.signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,(C14NMethodParameterSpec) null);
		SignatureMethod signatureMethod = this.signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
		SignedInfo signedInfo = this.signatureFactory.newSignedInfo(canonicalizationMethod,signatureMethod,Collections.singletonList(reference));
		DOMSignContext signContext = new DOMSignContext(gerenciadorDeKeystore.getPrivateKey(), document.getDocumentElement());
		KeyInfo keyInfo = this.criarKeyInfo();
		this.assinar(signContext, signedInfo, keyInfo);
	}

	public boolean verificarAssinaturaDoXML(Document document) throws KeyStoreException, MarshalException, XMLSignatureException {
		Element element = document.getDocumentElement();
		NodeList listOfSignatureElement =  element.getElementsByTagName("Signature");
		if (listOfSignatureElement.getLength() == 0) throw new XMLSignatureException("Nao encontrado elemento de assinatura");
		Node signatureElement = listOfSignatureElement.item(0);
		DOMValidateContext validateContext = new DOMValidateContext(gerenciadorDeKeystore.getPublicKey(), signatureElement);
		XMLSignature signature = this.signatureFactory.unmarshalXMLSignature(validateContext);
		return signature.validate(validateContext);
	}

	public void assinar(DOMSignContext signContext, SignedInfo signedInfo, KeyInfo keyInfo) throws KeyStoreException, MarshalException, XMLSignatureException, TransformerException {
		XMLSignature signature = this.signatureFactory.newXMLSignature(signedInfo, keyInfo);
		signature.sign(signContext);
	}

	public KeyInfo criarKeyInfo() throws KeyStoreException {
		KeyInfoFactory keyInfoFactory = this.signatureFactory.getKeyInfoFactory();
		List<X509Certificate> x509Content = this.recuperarListaDeCertificados();
		X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
		return keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
	}

	public List<X509Certificate> recuperarListaDeCertificados() throws KeyStoreException {
		X509Certificate certificate  = this.gerenciadorDeKeystore.getCertificado();
		List<X509Certificate> x509Content = new ArrayList<X509Certificate>();
		x509Content.add(certificate);
		return x509Content;
	}
}

Controlando cadeias de certificados

November 12th, 2009 agnaldo4j 2 comments

Este artigo é para desenvolvedores que precisam trabalhar com:

1. Conexão a webservices protegidos por cadeias de certificados digitais.

2. Controlar cadeias de certificados durante um processamento.

3. Trabalhar com tokens  PKCS11.

4. Trabalhar com certificados PKCS12 fornecidos por orgãos como SERASA (E-CPF,  E-CNPJ).

Antes de começar.

Para realizar os procedimentos deste artigo é necessário fazer o download do pacote Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy do site da sun, com este pacote podemos trabalhar com certificados do tipo PKCS12, PKCS11.

Existe também uma ferramenta para  importar/exportar certificados, criar keystores e assinar arquivos, que serão muito úteis para os testes que serão feitos durante o desenvolvimento do seu software e até mesmo criar seus próprios certificados para seus clientes se um certificado raiz não for necessário.

Código.

package com.softsimples.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class GerenciadorDeKeystore  {
	private static final String PKCS11 = "PKCS11";
	private final KeyStore keyStore;
	private final char[] pwdKeystoreCliente;
	private final File arquivoKeystoreCliente;
	private String aliasKeystoreCliente;
	private final String tipoKeystoreCliente;
	private final File arquivoKeystoreServidor;
	private final char[] pwdKeystoreServidor;
	private final String tipoKeystoreServidor;

	public GerenciadorDeKeystore(String tipoKeystoreCliente, File arquivoKeysotreCliente, String aliasKeystoreCliente,
									 char[] pwdKeystoreCliente, String tipoKeystoreServidor, File arquivoKeystoreServidor,
									 char[] pwdKeystoreServidor) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {

		this.tipoKeystoreCliente     = tipoKeystoreCliente;
		this.arquivoKeystoreCliente  = arquivoKeysotreCliente;
		this.aliasKeystoreCliente    = aliasKeystoreCliente;
		this.pwdKeystoreCliente      = pwdKeystoreCliente;
		this.tipoKeystoreServidor    = tipoKeystoreServidor;
		this.arquivoKeystoreServidor = arquivoKeystoreServidor;
		this.pwdKeystoreServidor     = pwdKeystoreServidor;

		this.keyStore = carregarKeystore(this.tipoKeystoreCliente, this.pwdKeystoreCliente, this.arquivoKeystoreCliente);
	}

	private KeyStore carregarKeystore(String type, char[] pwd, File arquivo) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
		KeyStore store = null;
		if (type.equalsIgnoreCase(PKCS11)) {
			Provider p = new sun.security.pkcs11.SunPKCS11("pkcs11.cfg");
			Security.addProvider(p);
			store = KeyStore.getInstance(type);
			store.load(null, pwd);
			this.aliasKeystoreCliente = store.aliases().nextElement();
		} else {
			store = KeyStore.getInstance(type);
			store.load(new FileInputStream(arquivo), pwd);
		}
		return store;
	}

	public X509Certificate getCertificado() throws KeyStoreException {
		return (X509Certificate)this.keyStore.getCertificate(this.aliasKeystoreCliente);
	}

	public PrivateKey getPrivateKey() throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException {
		Key key = this.keyStore.getKey(this.aliasKeystoreCliente, pwdKeystoreCliente);
        return (key instanceof PrivateKey) ? (PrivateKey)key : null;
	}

	public PublicKey getPublicKey() throws KeyStoreException {
		Certificate certificate = this.getCertificado();
		return certificate.getPublicKey();
	}

	public void configurarConexaoSegura() {
		System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
		Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

		System.setProperty("javax.net.ssl.trustStoreType", this.tipoKeystoreServidor);
		System.setProperty("javax.net.ssl.trustStore", this.arquivoKeystoreServidor.getAbsolutePath());
		System.setProperty("javax.net.ssl.trustStorePassword", String.valueOf(this.pwdKeystoreServidor));

		if (tipoKeystoreCliente.equalsIgnoreCase(PKCS11)) {
			System.setProperty("javax.net.ssl.keyStore", "NONE");
			System.setProperty("javax.net.ssl.keyStoreType", this.tipoKeystoreCliente);
			System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-NFe");
			System.setProperty("javax.net.ssl.keyStoreAlias", this.aliasKeystoreCliente);
			System.setProperty("javax.net.ssl.keyStorePassword", String.valueOf(this.pwdKeystoreCliente));
		} else {
			System.setProperty("javax.net.ssl.keyStoreType", this.tipoKeystoreCliente);
			System.setProperty("javax.net.ssl.keyStore", this.arquivoKeystoreCliente.getAbsolutePath());
			System.setProperty("javax.net.ssl.keyStorePassword", String.valueOf(this.pwdKeystoreCliente));
		}
	}
}

Projetos de estudos disponíveis

November 4th, 2009 agnaldo4j No comments

Olá!

Nos últimos anos tenho trabalhado em alguns pequenos projetos que vieram a ser uma ferramenta muito útil para meu aprendizado contínuo e na forma como eu desenvolvo software.

Com a intenção de compartilhar estas idéias com outros desenvolvedores, os projetos estão disponíveis no github.

Caso tenha alguma dificuldade com o git, leia o livro online sobre o assunto.

Vou comentar meus desenvolvimentos e a evolução de cada projeto.

SoftSimples.com

Categories: Padrão Tags: