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,6 +7,7 @@ | ||
| 7 | package org.demoiselle.jee.core.interfaces.security; | 7 | package org.demoiselle.jee.core.interfaces.security; |
| 8 | 8 | ||
| 9 | import java.io.Serializable; | 9 | import java.io.Serializable; |
| 10 | +import java.security.PublicKey; | ||
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| 12 | * <p> | 13 | * <p> |
| @@ -23,4 +24,6 @@ public interface TokensManager extends Serializable { | @@ -23,4 +24,6 @@ public interface TokensManager extends Serializable { | ||
| 23 | 24 | ||
| 24 | public boolean validate(); | 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,22 +31,23 @@ public class GenericExceptionMapper implements ExceptionMapper<Exception> { | ||
| 31 | 31 | ||
| 32 | StringWriter errorStackTrace = new StringWriter(); | 32 | StringWriter errorStackTrace = new StringWriter(); |
| 33 | ex.printStackTrace(new PrintWriter(errorStackTrace)); | 33 | ex.printStackTrace(new PrintWriter(errorStackTrace)); |
| 34 | + HashMap<String, String> entity = new HashMap<>(); | ||
| 34 | 35 | ||
| 35 | // Verifica se a exception é de validação de PAYLOAD do REST | 36 | // Verifica se a exception é de validação de PAYLOAD do REST |
| 36 | if (ex instanceof DemoiselleRESTException) { | 37 | if (ex instanceof DemoiselleRESTException) { |
| 37 | DemoiselleRESTException exDemoiselleREST = (DemoiselleRESTException) ex; | 38 | DemoiselleRESTException exDemoiselleREST = (DemoiselleRESTException) ex; |
| 38 | if (!exDemoiselleREST.getMessages().isEmpty()) { | 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 | .type(APPLICATION_JSON).build(); | 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 | .type(APPLICATION_JSON).build(); | 46 | .type(APPLICATION_JSON).build(); |
| 44 | } | 47 | } |
| 45 | 48 | ||
| 46 | } | 49 | } |
| 47 | 50 | ||
| 48 | - HashMap<String, String> entity = new HashMap<>(); | ||
| 49 | - | ||
| 50 | // No caso de existir message ele mostra a MESSAGE da Exception | 51 | // No caso de existir message ele mostra a MESSAGE da Exception |
| 51 | if (ex.getMessage() != null) { | 52 | if (ex.getMessage() != null) { |
| 52 | entity.put("error", ex.getMessage()); | 53 | entity.put("error", ex.getMessage()); |
| @@ -55,7 +56,7 @@ public class GenericExceptionMapper implements ExceptionMapper<Exception> { | @@ -55,7 +56,7 @@ public class GenericExceptionMapper implements ExceptionMapper<Exception> { | ||
| 55 | int level = 1; | 56 | int level = 1; |
| 56 | while (ex.getCause() != null) { | 57 | while (ex.getCause() != null) { |
| 57 | ex = (Exception) ex.getCause(); | 58 | ex = (Exception) ex.getCause(); |
| 58 | - if (!ex.getMessage().isEmpty()) { | 59 | + if (ex != null && ex.getMessage() != null && !ex.getMessage().isEmpty()) { |
| 59 | entity.put("inner_cause_" + level, ex.getMessage()); | 60 | entity.put("inner_cause_" + level, ex.getMessage()); |
| 60 | } | 61 | } |
| 61 | level += 1; | 62 | level += 1; |
demoiselle-security-jwt/pom.xml
| @@ -24,6 +24,11 @@ | @@ -24,6 +24,11 @@ | ||
| 24 | </dependency> | 24 | </dependency> |
| 25 | 25 | ||
| 26 | <dependency> | 26 | <dependency> |
| 27 | + <groupId>org.demoiselle.jee</groupId> | ||
| 28 | + <artifactId>demoiselle-configuration</artifactId> | ||
| 29 | + </dependency> | ||
| 30 | + | ||
| 31 | + <dependency> | ||
| 27 | <groupId>org.bitbucket.b_c</groupId> | 32 | <groupId>org.bitbucket.b_c</groupId> |
| 28 | <artifactId>jose4j</artifactId> | 33 | <artifactId>jose4j</artifactId> |
| 29 | <version>0.5.2</version> | 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 @@ | @@ -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,15 +5,20 @@ | ||
| 5 | */ | 5 | */ |
| 6 | package org.demoiselle.jee.security.jwt.impl; | 6 | package org.demoiselle.jee.security.jwt.impl; |
| 7 | 7 | ||
| 8 | +import java.security.PublicKey; | ||
| 8 | import java.util.List; | 9 | import java.util.List; |
| 9 | import java.util.Map; | 10 | import java.util.Map; |
| 11 | +import java.util.logging.Level; | ||
| 10 | import java.util.logging.Logger; | 12 | import java.util.logging.Logger; |
| 13 | +import javax.annotation.PostConstruct; | ||
| 14 | +import javax.enterprise.context.ApplicationScoped; | ||
| 11 | import javax.enterprise.context.RequestScoped; | 15 | import javax.enterprise.context.RequestScoped; |
| 12 | import javax.inject.Inject; | 16 | import javax.inject.Inject; |
| 13 | import javax.servlet.http.HttpServletRequest; | 17 | import javax.servlet.http.HttpServletRequest; |
| 14 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; | 18 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; |
| 15 | import org.demoiselle.jee.core.interfaces.security.Token; | 19 | import org.demoiselle.jee.core.interfaces.security.Token; |
| 16 | import org.demoiselle.jee.core.interfaces.security.TokensManager; | 20 | import org.demoiselle.jee.core.interfaces.security.TokensManager; |
| 21 | +import org.demoiselle.jee.security.exception.DemoiselleSecurityException; | ||
| 17 | import org.jose4j.jwk.JsonWebKey; | 22 | import org.jose4j.jwk.JsonWebKey; |
| 18 | import org.jose4j.jwk.RsaJsonWebKey; | 23 | import org.jose4j.jwk.RsaJsonWebKey; |
| 19 | import org.jose4j.jwk.RsaJwkGenerator; | 24 | import org.jose4j.jwk.RsaJwkGenerator; |
| @@ -43,14 +48,37 @@ public class TokensManagerImpl implements TokensManager { | @@ -43,14 +48,37 @@ public class TokensManagerImpl implements TokensManager { | ||
| 43 | @Inject | 48 | @Inject |
| 44 | private Token token; | 49 | private Token token; |
| 45 | 50 | ||
| 51 | +// @Inject | ||
| 52 | +// private Config config; | ||
| 46 | @Inject | 53 | @Inject |
| 47 | private DemoisellePrincipal loggedUser; | 54 | private DemoisellePrincipal loggedUser; |
| 48 | 55 | ||
| 49 | - public TokensManagerImpl() throws JoseException { | 56 | + //@PostConstruct |
| 57 | + public TokensManagerImpl() { | ||
| 50 | if (rsaJsonWebKey == null) { | 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,7 +91,6 @@ public class TokensManagerImpl implements TokensManager { | ||
| 63 | .setAllowedClockSkewInSeconds(60) // allow some leeway in validating time based claims to account for clock skew | 91 | .setAllowedClockSkewInSeconds(60) // allow some leeway in validating time based claims to account for clock skew |
| 64 | .setExpectedIssuer("demoiselle") // whom the JWT needs to have been issued by | 92 | .setExpectedIssuer("demoiselle") // whom the JWT needs to have been issued by |
| 65 | .setExpectedAudience("demoiselle") // to whom the JWT is intended for | 93 | .setExpectedAudience("demoiselle") // to whom the JWT is intended for |
| 66 | - .setDecryptionKey(rsaJsonWebKey.getPrivateKey()) // decrypt with the receiver's private key | ||
| 67 | .setVerificationKey(rsaJsonWebKey.getPublicKey()) | 94 | .setVerificationKey(rsaJsonWebKey.getPublicKey()) |
| 68 | .build(); // create the JwtConsumer instance | 95 | .build(); // create the JwtConsumer instance |
| 69 | JwtClaims jwtClaims = jwtConsumer.processToClaims(token.getKey()); | 96 | JwtClaims jwtClaims = jwtConsumer.processToClaims(token.getKey()); |
| @@ -111,7 +138,6 @@ public class TokensManagerImpl implements TokensManager { | @@ -111,7 +138,6 @@ public class TokensManagerImpl implements TokensManager { | ||
| 111 | token.setKey(jws.getCompactSerialization()); | 138 | token.setKey(jws.getCompactSerialization()); |
| 112 | token.setType("JWT"); | 139 | token.setType("JWT"); |
| 113 | } catch (JoseException ex) { | 140 | } catch (JoseException ex) { |
| 114 | - //ex.printStackTrace(); | ||
| 115 | logger.severe(ex.getMessage()); | 141 | logger.severe(ex.getMessage()); |
| 116 | } | 142 | } |
| 117 | 143 | ||
| @@ -122,4 +148,8 @@ public class TokensManagerImpl implements TokensManager { | @@ -122,4 +148,8 @@ public class TokensManagerImpl implements TokensManager { | ||
| 122 | return getUser() != null; | 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,6 +5,7 @@ | ||
| 5 | */ | 5 | */ |
| 6 | package org.demoiselle.jee.security.token.impl; | 6 | package org.demoiselle.jee.security.token.impl; |
| 7 | 7 | ||
| 8 | +import java.security.PublicKey; | ||
| 8 | import static java.util.UUID.randomUUID; | 9 | import static java.util.UUID.randomUUID; |
| 9 | import java.util.concurrent.ConcurrentHashMap; | 10 | import java.util.concurrent.ConcurrentHashMap; |
| 10 | import java.util.logging.Logger; | 11 | import java.util.logging.Logger; |
| @@ -59,4 +60,8 @@ public class TokensManagerImpl implements TokensManager { | @@ -59,4 +60,8 @@ public class TokensManagerImpl implements TokensManager { | ||
| 59 | return getUser() != null; | 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,8 +71,8 @@ public class RequiredPermissionInterceptor implements Serializable { | ||
| 71 | String resource = getResource(ic); | 71 | String resource = getResource(ic); |
| 72 | String operation = getOperation(ic); | 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 | if (!securityContext.hasPermission(resource, operation)) { | 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,6 +75,10 @@ public class RequiredRoleInterceptor implements Serializable { | ||
| 75 | List<String> roles = getRoles(ic); | 75 | List<String> roles = getRoles(ic); |
| 76 | 76 | ||
| 77 | List<String> userRoles = new ArrayList<>(); | 77 | List<String> userRoles = new ArrayList<>(); |
| 78 | + | ||
| 79 | + if (!securityContext.isLoggedIn()) { | ||
| 80 | + throw new DemoiselleSecurityException(bundle.userNotAuthenticated(), UNAUTHORIZED.getStatusCode()); | ||
| 81 | + } | ||
| 78 | 82 | ||
| 79 | for (String role : roles) { | 83 | for (String role : roles) { |
| 80 | if (securityContext.hasRole(role)) { | 84 | if (securityContext.hasRole(role)) { |