Commit 021d223bacede45579b1fc641a54998c41c624ad
1 parent
50340724
Ajustes segurança
Showing
10 changed files
with
149 additions
and
16 deletions
Show diff stats
demoiselle-core/src/main/java/org/demoiselle/jee/core/interfaces/security/TokensManager.java
| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | package org.demoiselle.jee.core.interfaces.security; |
| 8 | 8 | |
| 9 | 9 | import java.io.Serializable; |
| 10 | +import java.security.PublicKey; | |
| 10 | 11 | |
| 11 | 12 | /** |
| 12 | 13 | * <p> |
| ... | ... | @@ -23,4 +24,6 @@ public interface TokensManager extends Serializable { |
| 23 | 24 | |
| 24 | 25 | public boolean validate(); |
| 25 | 26 | |
| 27 | + public PublicKey getPublicKey(); | |
| 28 | + | |
| 26 | 29 | } | ... | ... |
demoiselle-rest/src/main/java/org/demoiselle/jee/ws/jaxrs/exception/mapper/GenericExceptionMapper.java
| ... | ... | @@ -31,22 +31,23 @@ public class GenericExceptionMapper implements ExceptionMapper<Exception> { |
| 31 | 31 | |
| 32 | 32 | StringWriter errorStackTrace = new StringWriter(); |
| 33 | 33 | ex.printStackTrace(new PrintWriter(errorStackTrace)); |
| 34 | + HashMap<String, String> entity = new HashMap<>(); | |
| 34 | 35 | |
| 35 | 36 | // Verifica se a exception é de validação de PAYLOAD do REST |
| 36 | 37 | if (ex instanceof DemoiselleRESTException) { |
| 37 | 38 | DemoiselleRESTException exDemoiselleREST = (DemoiselleRESTException) ex; |
| 38 | 39 | if (!exDemoiselleREST.getMessages().isEmpty()) { |
| 39 | - return status(exDemoiselleREST.getStatusCode()).entity(exDemoiselleREST.getMessages()) | |
| 40 | + entity.put("error", exDemoiselleREST.getMessages().toString()); | |
| 41 | + return status(exDemoiselleREST.getStatusCode()).entity(entity) | |
| 40 | 42 | .type(APPLICATION_JSON).build(); |
| 41 | - } else if (exDemoiselleREST.getStatusCode() > 0){ | |
| 42 | - return status(exDemoiselleREST.getStatusCode()).entity(exDemoiselleREST.getMessage()) | |
| 43 | + } else if (exDemoiselleREST.getStatusCode() > 0) { | |
| 44 | + entity.put("error", exDemoiselleREST.getMessage()); | |
| 45 | + return status(exDemoiselleREST.getStatusCode()).entity(entity) | |
| 43 | 46 | .type(APPLICATION_JSON).build(); |
| 44 | 47 | } |
| 45 | 48 | |
| 46 | 49 | } |
| 47 | 50 | |
| 48 | - HashMap<String, String> entity = new HashMap<>(); | |
| 49 | - | |
| 50 | 51 | // No caso de existir message ele mostra a MESSAGE da Exception |
| 51 | 52 | if (ex.getMessage() != null) { |
| 52 | 53 | entity.put("error", ex.getMessage()); |
| ... | ... | @@ -55,7 +56,7 @@ public class GenericExceptionMapper implements ExceptionMapper<Exception> { |
| 55 | 56 | int level = 1; |
| 56 | 57 | while (ex.getCause() != null) { |
| 57 | 58 | ex = (Exception) ex.getCause(); |
| 58 | - if (!ex.getMessage().isEmpty()) { | |
| 59 | + if (ex != null && ex.getMessage() != null && !ex.getMessage().isEmpty()) { | |
| 59 | 60 | entity.put("inner_cause_" + level, ex.getMessage()); |
| 60 | 61 | } |
| 61 | 62 | level += 1; | ... | ... |
demoiselle-security-jwt/pom.xml
| ... | ... | @@ -24,6 +24,11 @@ |
| 24 | 24 | </dependency> |
| 25 | 25 | |
| 26 | 26 | <dependency> |
| 27 | + <groupId>org.demoiselle.jee</groupId> | |
| 28 | + <artifactId>demoiselle-configuration</artifactId> | |
| 29 | + </dependency> | |
| 30 | + | |
| 31 | + <dependency> | |
| 27 | 32 | <groupId>org.bitbucket.b_c</groupId> |
| 28 | 33 | <artifactId>jose4j</artifactId> |
| 29 | 34 | <version>0.5.2</version> | ... | ... |
demoiselle-security-jwt/src/main/java/org/demoiselle/jee/security/jwt/impl/Config.java
0 → 100644
| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | +/* | |
| 2 | + * To change this license header, choose License Headers in Project Properties. | |
| 3 | + * To change this template file, choose Tools | Templates | |
| 4 | + * and open the template in the editor. | |
| 5 | + */ | |
| 6 | +package org.demoiselle.jee.security.jwt.impl; | |
| 7 | + | |
| 8 | +import java.io.Serializable; | |
| 9 | +import org.demoiselle.jee.configuration.annotation.Configuration; | |
| 10 | +import org.demoiselle.jee.core.annotation.Name; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * | |
| 14 | + * @author 70744416353 | |
| 15 | + */ | |
| 16 | +@Configuration(resource = "demoiselle-security-jwt") | |
| 17 | +public class Config implements Serializable { | |
| 18 | + | |
| 19 | + private static final long serialVersionUID = 638435989235076782L; | |
| 20 | + | |
| 21 | + @Name("jwt.type") | |
| 22 | + private String type; | |
| 23 | + | |
| 24 | + @Name("jwt.privateKey") | |
| 25 | + private String privateKey; | |
| 26 | + | |
| 27 | + @Name("jwt.publicKey") | |
| 28 | + private String publicKey; | |
| 29 | + | |
| 30 | + @Name("jwt.timetolive") | |
| 31 | + private Float tempo; | |
| 32 | + | |
| 33 | + @Name("jwt.issuer") | |
| 34 | + private String remetente; | |
| 35 | + | |
| 36 | + @Name("jwt.audience") | |
| 37 | + private String destinatario; | |
| 38 | + | |
| 39 | + public String getType() { | |
| 40 | + return type; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public void setType(String type) { | |
| 44 | + this.type = type; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public String getPrivateKey() { | |
| 48 | + return privateKey; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public void setPrivateKey(String privateKey) { | |
| 52 | + this.privateKey = privateKey; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public String getPublicKey() { | |
| 56 | + return publicKey; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public void setPublicKey(String publicKey) { | |
| 60 | + this.publicKey = publicKey; | |
| 61 | + } | |
| 62 | + | |
| 63 | + public Float getTempo() { | |
| 64 | + return tempo; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public void setTempo(Float tempo) { | |
| 68 | + this.tempo = tempo; | |
| 69 | + } | |
| 70 | + | |
| 71 | + public String getRemetente() { | |
| 72 | + return remetente; | |
| 73 | + } | |
| 74 | + | |
| 75 | + public void setRemetente(String remetente) { | |
| 76 | + this.remetente = remetente; | |
| 77 | + } | |
| 78 | + | |
| 79 | + public String getDestinatario() { | |
| 80 | + return destinatario; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public void setDestinatario(String destinatario) { | |
| 84 | + this.destinatario = destinatario; | |
| 85 | + } | |
| 86 | + | |
| 87 | +} | ... | ... |
demoiselle-security-jwt/src/main/java/org/demoiselle/jee/security/jwt/impl/TokensManagerImpl.java
| ... | ... | @@ -5,15 +5,20 @@ |
| 5 | 5 | */ |
| 6 | 6 | package org.demoiselle.jee.security.jwt.impl; |
| 7 | 7 | |
| 8 | +import java.security.PublicKey; | |
| 8 | 9 | import java.util.List; |
| 9 | 10 | import java.util.Map; |
| 11 | +import java.util.logging.Level; | |
| 10 | 12 | import java.util.logging.Logger; |
| 13 | +import javax.annotation.PostConstruct; | |
| 14 | +import javax.enterprise.context.ApplicationScoped; | |
| 11 | 15 | import javax.enterprise.context.RequestScoped; |
| 12 | 16 | import javax.inject.Inject; |
| 13 | 17 | import javax.servlet.http.HttpServletRequest; |
| 14 | 18 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; |
| 15 | 19 | import org.demoiselle.jee.core.interfaces.security.Token; |
| 16 | 20 | import org.demoiselle.jee.core.interfaces.security.TokensManager; |
| 21 | +import org.demoiselle.jee.security.exception.DemoiselleSecurityException; | |
| 17 | 22 | import org.jose4j.jwk.JsonWebKey; |
| 18 | 23 | import org.jose4j.jwk.RsaJsonWebKey; |
| 19 | 24 | import org.jose4j.jwk.RsaJwkGenerator; |
| ... | ... | @@ -43,14 +48,37 @@ public class TokensManagerImpl implements TokensManager { |
| 43 | 48 | @Inject |
| 44 | 49 | private Token token; |
| 45 | 50 | |
| 51 | +// @Inject | |
| 52 | +// private Config config; | |
| 46 | 53 | @Inject |
| 47 | 54 | private DemoisellePrincipal loggedUser; |
| 48 | 55 | |
| 49 | - public TokensManagerImpl() throws JoseException { | |
| 56 | + //@PostConstruct | |
| 57 | + public TokensManagerImpl() { | |
| 50 | 58 | if (rsaJsonWebKey == null) { |
| 51 | - String chave = RsaJwkGenerator.generateJwk(2048).toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE); | |
| 52 | - rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk(chave); | |
| 53 | - rsaJsonWebKey.setKeyId("demoiselle-security-jwt"); | |
| 59 | +// logger.info("Demoiselle Module - Security - JWT"); | |
| 60 | + try { | |
| 61 | + | |
| 62 | +// if (config.getType() == null) { | |
| 63 | +// throw new DemoiselleSecurityException("Escolha o tipo de autenticação, ver documentação", 500); | |
| 64 | +// } | |
| 65 | +// | |
| 66 | +// if (config.getType().equalsIgnoreCase("slave") && (config.getPublicKey() == null || config.getPublicKey().isEmpty())) { | |
| 67 | +// throw new DemoiselleSecurityException("Informe a chave pública no arquivo de configuração do projeto, ver documentação", 500); | |
| 68 | +// } else { | |
| 69 | +// rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk(config.getPrivateKey()); | |
| 70 | +// } | |
| 71 | +// | |
| 72 | +// if (config.getType().equalsIgnoreCase("master") && (config.getPrivateKey() == null || config.getPrivateKey().isEmpty())) { | |
| 73 | +// throw new DemoiselleSecurityException("Informe a chave privada no arquivo de configuração do projeto, ver documentação", 500); | |
| 74 | +// } else { | |
| 75 | +// rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk(config.getPublicKey()); | |
| 76 | +// } | |
| 77 | + rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk(RsaJwkGenerator.generateJwk(2048).toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE)); | |
| 78 | + rsaJsonWebKey.setKeyId("demoiselle-security-jwt"); | |
| 79 | + } catch (JoseException ex) { | |
| 80 | + // logger.severe(ex.getMessage()); | |
| 81 | + } | |
| 54 | 82 | } |
| 55 | 83 | } |
| 56 | 84 | |
| ... | ... | @@ -63,7 +91,6 @@ public class TokensManagerImpl implements TokensManager { |
| 63 | 91 | .setAllowedClockSkewInSeconds(60) // allow some leeway in validating time based claims to account for clock skew |
| 64 | 92 | .setExpectedIssuer("demoiselle") // whom the JWT needs to have been issued by |
| 65 | 93 | .setExpectedAudience("demoiselle") // to whom the JWT is intended for |
| 66 | - .setDecryptionKey(rsaJsonWebKey.getPrivateKey()) // decrypt with the receiver's private key | |
| 67 | 94 | .setVerificationKey(rsaJsonWebKey.getPublicKey()) |
| 68 | 95 | .build(); // create the JwtConsumer instance |
| 69 | 96 | JwtClaims jwtClaims = jwtConsumer.processToClaims(token.getKey()); |
| ... | ... | @@ -111,7 +138,6 @@ public class TokensManagerImpl implements TokensManager { |
| 111 | 138 | token.setKey(jws.getCompactSerialization()); |
| 112 | 139 | token.setType("JWT"); |
| 113 | 140 | } catch (JoseException ex) { |
| 114 | - //ex.printStackTrace(); | |
| 115 | 141 | logger.severe(ex.getMessage()); |
| 116 | 142 | } |
| 117 | 143 | |
| ... | ... | @@ -122,4 +148,8 @@ public class TokensManagerImpl implements TokensManager { |
| 122 | 148 | return getUser() != null; |
| 123 | 149 | } |
| 124 | 150 | |
| 151 | + @Override | |
| 152 | + public PublicKey getPublicKey() { | |
| 153 | + return rsaJsonWebKey.getPublicKey(); | |
| 154 | + } | |
| 125 | 155 | } | ... | ... |
demoiselle-security-jwt/src/main/resources/demoiselle.properties
demoiselle-security-jwt/src/main/resources/messages.properties
demoiselle-security-token/src/main/java/org/demoiselle/jee/security/token/impl/TokensManagerImpl.java
| ... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 | */ |
| 6 | 6 | package org.demoiselle.jee.security.token.impl; |
| 7 | 7 | |
| 8 | +import java.security.PublicKey; | |
| 8 | 9 | import static java.util.UUID.randomUUID; |
| 9 | 10 | import java.util.concurrent.ConcurrentHashMap; |
| 10 | 11 | import java.util.logging.Logger; |
| ... | ... | @@ -59,4 +60,8 @@ public class TokensManagerImpl implements TokensManager { |
| 59 | 60 | return getUser() != null; |
| 60 | 61 | } |
| 61 | 62 | |
| 63 | + @Override | |
| 64 | + public PublicKey getPublicKey() { | |
| 65 | + return null; | |
| 66 | + } | |
| 62 | 67 | } | ... | ... |
demoiselle-security/src/main/java/org/demoiselle/jee/security/interceptor/RequiredPermissionInterceptor.java
| ... | ... | @@ -71,8 +71,8 @@ public class RequiredPermissionInterceptor implements Serializable { |
| 71 | 71 | String resource = getResource(ic); |
| 72 | 72 | String operation = getOperation(ic); |
| 73 | 73 | |
| 74 | - if (securityContext.isLoggedIn()) { | |
| 75 | - logger.finest(bundle.accessCheckingPermission(operation, resource)); | |
| 74 | + if (!securityContext.isLoggedIn()) { | |
| 75 | + throw new DemoiselleSecurityException(bundle.userNotAuthenticated(), UNAUTHORIZED.getStatusCode()); | |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | if (!securityContext.hasPermission(resource, operation)) { | ... | ... |
demoiselle-security/src/main/java/org/demoiselle/jee/security/interceptor/RequiredRoleInterceptor.java
| ... | ... | @@ -75,6 +75,10 @@ public class RequiredRoleInterceptor implements Serializable { |
| 75 | 75 | List<String> roles = getRoles(ic); |
| 76 | 76 | |
| 77 | 77 | List<String> userRoles = new ArrayList<>(); |
| 78 | + | |
| 79 | + if (!securityContext.isLoggedIn()) { | |
| 80 | + throw new DemoiselleSecurityException(bundle.userNotAuthenticated(), UNAUTHORIZED.getStatusCode()); | |
| 81 | + } | |
| 78 | 82 | |
| 79 | 83 | for (String role : roles) { |
| 80 | 84 | if (securityContext.hasRole(role)) { | ... | ... |