Skip to content

Commit

Permalink
Adicionado gerador de hash e jwt builder
Browse files Browse the repository at this point in the history
  • Loading branch information
dearrudam committed Mar 12, 2022
1 parent e2d9ad1 commit cafaa85
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 4 deletions.
12 changes: 8 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-rest-data-panache</artifactId>
Expand All @@ -74,15 +73,20 @@
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-links</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-jwt-build</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/io/github/arrudalabs/mizudo/model/Membro.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public static Optional<Membro> buscarPorId(Long id) {
return Membro.findByIdOptional(id);
}

/**
* Método dedicado para testes
* Não utilizar em produção
*/
@Deprecated
public static void removerTodosMembros() {
List<Membro> membros = Membro.listAll();
membros.stream().forEach(Membro::apagar);
Expand Down Expand Up @@ -81,6 +86,8 @@ private void apagar() {
this.emails.clear();
this.telefones.clear();
this.examesMedicos.clear();
Usuario.buscarUsuariosDoMembro(this)
.forEach(Usuario::delete);
this.persist();
this.delete();
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/io/github/arrudalabs/mizudo/model/Usuario.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,27 @@
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;

import javax.persistence.*;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

@Entity
@Table(name = "usuarios")
public class Usuario extends PanacheEntityBase {

public static Stream<Usuario> buscarUsuariosDoMembro(Membro membro) {
return Usuario.stream("membro.id = :membroId", Map.of("membroId", membro.id));
}

/**
* Método dedicado aos testes
* Não utilizar esse método em produção
*/
@Deprecated
public static void apagarTodosOsUsuarios() {
Usuario.deleteAll();
}

@Id
public String username;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.github.arrudalabs.mizudo.resources.membros;

import io.github.arrudalabs.mizudo.model.Membro;
import io.github.arrudalabs.mizudo.model.Usuario;
import io.github.arrudalabs.mizudo.validation.DeveSerIdValido;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/membros/{membroId}/user")
public class UsuarioDoMembroResource {

@PUT
public UsuarioRegistrado definirUsuario(
@DeveSerIdValido(
entityClass = Membro.class,
message = "Membro inválido"
)
@PathParam("membroId") final Long membroId,
@Valid final NovoUsuario novoUsuario) {

return UsuarioRegistrado.of(novoUsuario.definirUsuario(membroId));
}

public static class NovoUsuario {

@NotBlank
public String username;
@NotBlank
public String senha;
@NotBlank
public String confirmacaoSenha;

public Usuario definirUsuario(Long membroId) {
var usuario = new Usuario();
usuario.username = this.username;
//TODO implementar
return usuario;
}
}

public static class UsuarioRegistrado {

public static UsuarioRegistrado of(Usuario usuario) {
var usuarioRegistrado = new UsuarioRegistrado();
usuarioRegistrado.username = usuario.username;
return usuarioRegistrado;
}

public String username;
public String senha = "*****";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.github.arrudalabs.mizudo.services;

import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.enterprise.context.ApplicationScoped;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@ApplicationScoped
public class GeradorDeHash {

@ConfigProperty(name = "gerador.senha.algoritmo",defaultValue = "PBKDF2WithHmacSHA512")
private String algoritmo;
@ConfigProperty(name = "gerador.senha.iteracoes",defaultValue = "150000")
private Integer iteracoes;
@ConfigProperty(name = "gerador.senha.tamanho.chave",defaultValue = "32")
private Integer tamanhoChave;

public String gerarHash(String salt, String senha){
try {
var hash = SecretKeyFactory.getInstance(this.algoritmo)
.generateSecret(
new PBEKeySpec(
senha.toCharArray(),
salt.getBytes(StandardCharsets.UTF_8),
this.iteracoes,
this.tamanhoChave
)
).getEncoded();
return Base64.getEncoder().encodeToString(hash);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.github.arrudalabs.mizudo.services;

import io.smallrye.jwt.build.Jwt;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.enterprise.context.ApplicationScoped;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

@ApplicationScoped
public class JwtTokenBuilder {

private final Long duracaoEmMinutos;
private final String privateKey;
private final String issuer;
private final String keyId;

public JwtTokenBuilder(
@ConfigProperty(name = "jwt.token.duracao.minutos", defaultValue = "300") final Long duracaoEmMinutos,
@ConfigProperty(name = "jwt.private.key") final String privateKey,
@ConfigProperty(name = "jwt.issuer") final String issuer
) {
this.duracaoEmMinutos = duracaoEmMinutos;
this.privateKey = privateKey;
this.issuer = issuer;
this.keyId = UUID.randomUUID().toString();
}

public String gerarToken(String username,
Set<String> papeis) throws NoSuchAlgorithmException, InvalidKeySpecException {

long currentTimeInSecs = System.currentTimeMillis() / 1000;
var claimsBuilder = Jwt.claims();
PrivateKey privateKey = decodePrivateKey();

claimsBuilder.issuer(this.issuer);
claimsBuilder.subject(username);
claimsBuilder.issuedAt(currentTimeInSecs);
claimsBuilder.expiresAt(tempoDeExpiracao(currentTimeInSecs));
claimsBuilder.groups(papeis);

return claimsBuilder.jws().keyId(this.keyId).sign(privateKey);
}

private PrivateKey decodePrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
var decodedKey = Base64.getDecoder().decode(this.privateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
KeyFactory keyFactory=KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}

public long tempoDeExpiracao(long currentTimeInSecs) {
return currentTimeInSecs + (this.duracaoEmMinutos * 60);
}

}
4 changes: 4 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ quarkus.datasource.username=username-default
quarkus.datasource.jdbc.url=jdbc:h2:mem:default
quarkus.datasource.jdbc.max-size=13

jwt.issuer=https://mizudo-app.com
jwt.private.key=MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCXrLzooX0pXJ7N13Z9A9FP1TdW2IWsrCWgPzwi1jiTTj/DRw4jVHvfEuts1P6mp/XwrlWdqpq54GsFO7x2/KqjgmbOnbzWJQNSBfnu+NZV2M3SLu8oUwEBOL2+qosix8EzaG7s8JruMdkfzHnuizpkiVigDckOL5LNGuElyvElf436c0RcN4dGOcHaZHJEOs9s0Ep5TFz0xfEJaw/PxItam+Uxl69olWJXUKd5dgMwyPw9txgXvQX7rjkCc9N6SeW+vCErgN0G5HeF/H+D2f0Mnpg0S3cFlyQbomJ05XsFC2o0m8znGtct0cYDCjsF4Acqyk/B1GytkH0io5y6PUU7AgMBAAECggEAMxUCKnb46E1BTqIaTdBTVkfA84bIvnbb1TR21GTBeRsJboMnx85USbTdhTHW8dnvgre0Lf2fTqq+YGzV9Fz0O01Xwo5tYtHkZGOO4WT9CryR1Q/pi/Moi3jIrsZRRc1wzBeIBFSkWUSAk60SA7zwVZvMNVtvM0/iaSF8YnYO8UmXkARbWpfypAgiW7sk3BRWavpYrjQ9tygjHeWi9nxmuL/yZUT9+ojEvdFsedOG1oofEe7a4jz2ftvJTJlMS4IpEBql5OxhrAAkjHyu0AXaiPnhzXezdoZNlAqXXrG9XfklAgoxbKSfucZaR2Fk35vsaY1FW2A40a1ojqUTXrqgwQKBgQDIYDyUW/1JFEVJ7VWv9j4ZutKRUGoSUeDnRUCjkwSyQD/9D5gW/DduofIIkEr0d45m6Dpr8/1ke8joutgw35WJepFGjCbV+VKM5gYwxPElIVuZHOqU5pVAREtgslEJGEeJSUFt/XBIDnh8SOSERZoxp2rD1+6Je2l55lVb1FkcvQKBgQDBx4qHL8oAoYu692LRQJylX2bPDRVfMhcd7IT5IiB40qZg4Zx2ATZXGZnim5kYcTb+CzBArekZJpujgWJgBSZACF6PSME5J1gCyeM/eVuXcgfEFg/eheNQvwcT1rOqzoilUCEUskt+iDh8sZF7ugv7Hwz6gjCgFrU6xKM5Jw0VVwKBgAm8IzVSAsw6H+OnlDIoVHwLh49nyL97GuIhizJnQiMm2/T/fPQg7NCDLa8c04dtB44YWj5EbFslaG1mJnq5Yhp7yfMTfA+JPWl7A3H7H3weUsTtkrgJO9cTelYIU8eNVmxlEri1R284xMHFCNUkTIl9CMLbCsvDIyy49AyyFGJBAoGAJ2rCh/s1mOlDdhWqWSxOcOk2DXn41fNndmPNLKw/dLRMubpKzEo01oTTo5/JBYrKB+UYvJ9jogUTda/05dlGTZImQfknrMuPAIo2movCEM1WPRHLypTrh1pEQ0nSJDV84Durbv1Rk/x7mQm5sTRICZ3oUvC2mWnlFX44QYDrDWMCgYBUsqFh5MymEd+fky0vtpqcn+2HHlnxWpx7oTs3AVQNX4UDaKTSOcXAweiBjwLpgfhijdR/dph/92C8uL0q6SEel7FR06XlqDUzbG2p4IOZt4SVuXkCuYhFcl6xzAj1s/+ewnaCc4ETolWoJw3/3brbQGyT8PeK7BZqVHdMAv3iUA==
jwt.token.duracao.minutos=1

%dev.quarkus.datasource.db-kind=h2
%dev.quarkus.datasource.username=username-default
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:default
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.github.arrudalabs.mizudo.resources.membros;

import io.github.arrudalabs.mizudo.model.Membro;
import io.github.arrudalabs.mizudo.model.Usuario;
import io.github.arrudalabs.mizudo.resources.ApiTestSupport;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.inject.Inject;
import javax.json.Json;
import javax.ws.rs.core.Response;

import java.util.Map;
import java.util.UUID;

import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;

@QuarkusTest
public class UsuarioDoMembroTest {

@Inject
ApiTestSupport apiTestSupport;

@BeforeEach
@AfterEach
void limparMembros(){
apiTestSupport.execute(Usuario::apagarTodosOsUsuarios);
apiTestSupport.execute(Membro::removerTodosMembros);
}

@Test
void deveDefinirUsuarioParaUmMembroValido(){

var membro = apiTestSupport.executeAndGet(()->Membro.novoMembro(UUID.randomUUID().toString()));

String senha = UUID.randomUUID().toString();
String username = UUID.randomUUID().toString();
apiTestSupport
.newAuthenticatedRequest()
.log().everything()
.contentType(ContentType.JSON)
.body(Json.createObjectBuilder()
.add("username", username)
.add("senha", senha)
.add("confirmacaoSenha",senha)
.build().toString())
.put("/resources/membros/{id}/user", Map.of("id",membro.id))
.then()
.log().everything()
.statusCode(Response.Status.OK.getStatusCode())
.body("username", is(username))
.body("senha", is("*****"));

}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.github.arrudalabs.mizudo.services;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import javax.inject.Inject;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Set;

@QuarkusTest
class JwtTokenBuilderTest {

@Inject
JwtTokenBuilder jwtTokenBuilder;

@Test
void deveGerarUmTokenValido() throws NoSuchAlgorithmException, InvalidKeySpecException {

System.out.println(jwtTokenBuilder.gerarToken("admin", Set.of("ADMIN", "USER")));

}


}

0 comments on commit cafaa85

Please sign in to comment.