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)) { | ... | ... |