Commit 986dccd716b77e3ab1e6dccec4c1b24ac670a8da
1 parent
6e126b79
Segurança e ajustes nos pacotes
Showing
16 changed files
with
301 additions
and
129 deletions
Show diff stats
demoiselle-parent/pom.xml
| @@ -179,6 +179,18 @@ | @@ -179,6 +179,18 @@ | ||
| 179 | <artifactId>demoiselle-security</artifactId> | 179 | <artifactId>demoiselle-security</artifactId> |
| 180 | <version>${project.version}</version> | 180 | <version>${project.version}</version> |
| 181 | </dependency> | 181 | </dependency> |
| 182 | + | ||
| 183 | + <dependency> | ||
| 184 | + <groupId>org.demoiselle.jee</groupId> | ||
| 185 | + <artifactId>demoiselle-rest</artifactId> | ||
| 186 | + <version>${project.version}</version> | ||
| 187 | + </dependency> | ||
| 188 | + | ||
| 189 | + <dependency> | ||
| 190 | + <groupId>org.demoiselle.jee</groupId> | ||
| 191 | + <artifactId>demoiselle-persistence-jpa</artifactId> | ||
| 192 | + <version>${project.version}</version> | ||
| 193 | + </dependency> | ||
| 182 | 194 | ||
| 183 | </dependencies> | 195 | </dependencies> |
| 184 | 196 |
demoiselle-rest/src/main/java/org/demoiselle/jee/ws/jaxrs/exception/DemoiselleRESTException.java
| @@ -12,30 +12,30 @@ import org.demoiselle.jee.core.exception.DemoiselleException; | @@ -12,30 +12,30 @@ import org.demoiselle.jee.core.exception.DemoiselleException; | ||
| 12 | 12 | ||
| 13 | public class DemoiselleRESTException extends DemoiselleException { | 13 | public class DemoiselleRESTException extends DemoiselleException { |
| 14 | 14 | ||
| 15 | - private static final long serialVersionUID = 519965615171844237L; | 15 | + private static final long serialVersionUID = 519965615171844237L; |
| 16 | 16 | ||
| 17 | - private HashMap<String, String> messages = new HashMap<String, String>(); | 17 | + private HashMap<String, String> messages = new HashMap<String, String>(); |
| 18 | 18 | ||
| 19 | - private int statusCode; | 19 | + private int statusCode; |
| 20 | 20 | ||
| 21 | - public DemoiselleRESTException() { | 21 | + public DemoiselleRESTException() { |
| 22 | 22 | ||
| 23 | - } | ||
| 24 | - | ||
| 25 | - public DemoiselleRESTException(String string) { | ||
| 26 | - super(string); | ||
| 27 | - } | 23 | + } |
| 28 | 24 | ||
| 29 | - public int getStatusCode() { | ||
| 30 | - return statusCode; | ||
| 31 | - } | 25 | + public DemoiselleRESTException(String string) { |
| 26 | + super(string); | ||
| 27 | + } | ||
| 32 | 28 | ||
| 33 | - public void addMessage(String field, String msg) { | ||
| 34 | - this.statusCode = 422; | ||
| 35 | - messages.put(field, msg); | ||
| 36 | - } | 29 | + public int getStatusCode() { |
| 30 | + return statusCode; | ||
| 31 | + } | ||
| 37 | 32 | ||
| 38 | - public HashMap<String, String> getMessages() { | ||
| 39 | - return messages; | ||
| 40 | - } | 33 | + public void addMessage(String field, String msg) { |
| 34 | + this.statusCode = 422; | ||
| 35 | + messages.put(field, msg); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public HashMap<String, String> getMessages() { | ||
| 39 | + return messages; | ||
| 40 | + } | ||
| 41 | } | 41 | } |
demoiselle-rest/src/main/java/org/demoiselle/jee/ws/jaxrs/exception/mapper/GenericExceptionMapper.java
| @@ -21,48 +21,52 @@ import org.demoiselle.jee.ws.jaxrs.exception.DemoiselleRESTException; | @@ -21,48 +21,52 @@ import org.demoiselle.jee.ws.jaxrs.exception.DemoiselleRESTException; | ||
| 21 | @Provider | 21 | @Provider |
| 22 | public class GenericExceptionMapper implements ExceptionMapper<Exception> { | 22 | public class GenericExceptionMapper implements ExceptionMapper<Exception> { |
| 23 | 23 | ||
| 24 | - public Response toResponse(Exception ex) { | 24 | + public Response toResponse(Exception ex) { |
| 25 | 25 | ||
| 26 | - StringWriter errorStackTrace = new StringWriter(); | ||
| 27 | - ex.printStackTrace(new PrintWriter(errorStackTrace)); | 26 | + StringWriter errorStackTrace = new StringWriter(); |
| 27 | + ex.printStackTrace(new PrintWriter(errorStackTrace)); | ||
| 28 | 28 | ||
| 29 | - // Verifica se a exception é de validação de PAYLOAD do REST | ||
| 30 | - if (ex.getCause() instanceof DemoiselleRESTException) { | ||
| 31 | - DemoiselleRESTException exDemoiselleREST = (DemoiselleRESTException) ex.getCause(); | ||
| 32 | - if (!exDemoiselleREST.getMessages().isEmpty()) { | ||
| 33 | - return Response.status(exDemoiselleREST.getStatusCode()).entity(exDemoiselleREST.getMessages()) | ||
| 34 | - .type(MediaType.APPLICATION_JSON).build(); | ||
| 35 | - } | ||
| 36 | - } | 29 | + // Verifica se a exception é de validação de PAYLOAD do REST |
| 30 | + if (ex instanceof DemoiselleRESTException) { | ||
| 31 | + DemoiselleRESTException exDemoiselleREST = (DemoiselleRESTException) ex; | ||
| 32 | + if (!exDemoiselleREST.getMessages().isEmpty()) { | ||
| 33 | + return Response.status(exDemoiselleREST.getStatusCode()).entity(exDemoiselleREST.getMessages()) | ||
| 34 | + .type(MediaType.APPLICATION_JSON).build(); | ||
| 35 | + } else if (exDemoiselleREST.getStatusCode() > 0){ | ||
| 36 | + return Response.status(exDemoiselleREST.getStatusCode()).entity(exDemoiselleREST.getMessage()) | ||
| 37 | + .type(MediaType.APPLICATION_JSON).build(); | ||
| 38 | + } | ||
| 37 | 39 | ||
| 38 | - HashMap<String, String> entity = new HashMap<String, String>(); | 40 | + } |
| 39 | 41 | ||
| 40 | - // No caso de existir message ele mostra a MESSAGE da Exception | ||
| 41 | - if (ex.getMessage() != null) { | ||
| 42 | - entity.put("error", ex.getMessage()); | 42 | + HashMap<String, String> entity = new HashMap<String, String>(); |
| 43 | 43 | ||
| 44 | - // Pega toda as mensagens da stacktrace | ||
| 45 | - int level = 1; | ||
| 46 | - while (ex.getCause() != null) { | ||
| 47 | - ex = (Exception) ex.getCause(); | ||
| 48 | - if (!ex.getMessage().isEmpty()) { | ||
| 49 | - entity.put("inner_cause_" + level, ex.getMessage()); | ||
| 50 | - } | ||
| 51 | - level += 1; | ||
| 52 | - } | ||
| 53 | - | ||
| 54 | - // Por padrão retorna SERVER ERROR, mas tenta encontrar o status do RESPONSE se for WebApplicationException | ||
| 55 | - // http://docs.oracle.com/javaee/7/api/javax/ws/rs/WebApplicationException.html | ||
| 56 | - int responseCode = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); | ||
| 57 | - if (ex instanceof WebApplicationException) { | ||
| 58 | - responseCode = ((WebApplicationException)ex).getResponse().getStatus(); | ||
| 59 | - } | 44 | + // No caso de existir message ele mostra a MESSAGE da Exception |
| 45 | + if (ex.getMessage() != null) { | ||
| 46 | + entity.put("error", ex.getMessage()); | ||
| 60 | 47 | ||
| 61 | - return Response.status(responseCode).entity(entity).type(MediaType.APPLICATION_JSON).build(); | ||
| 62 | - } | 48 | + // Pega toda as mensagens da stacktrace |
| 49 | + int level = 1; | ||
| 50 | + while (ex.getCause() != null) { | ||
| 51 | + ex = (Exception) ex.getCause(); | ||
| 52 | + if (!ex.getMessage().isEmpty()) { | ||
| 53 | + entity.put("inner_cause_" + level, ex.getMessage()); | ||
| 54 | + } | ||
| 55 | + level += 1; | ||
| 56 | + } | ||
| 63 | 57 | ||
| 64 | - entity.put("error", "Erro interno desconhecido no servidor."); | ||
| 65 | - return Response.status(500).entity(entity).type(MediaType.APPLICATION_JSON).build(); | ||
| 66 | - } | 58 | + // Por padrão retorna SERVER ERROR, mas tenta encontrar o status do RESPONSE se for WebApplicationException |
| 59 | + // http://docs.oracle.com/javaee/7/api/javax/ws/rs/WebApplicationException.html | ||
| 60 | + int responseCode = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); | ||
| 61 | + if (ex instanceof WebApplicationException) { | ||
| 62 | + responseCode = ((WebApplicationException) ex).getResponse().getStatus(); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + return Response.status(responseCode).entity(entity).type(MediaType.APPLICATION_JSON).build(); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + entity.put("error", "Erro interno desconhecido no servidor."); | ||
| 69 | + return Response.status(500).entity(entity).type(MediaType.APPLICATION_JSON).build(); | ||
| 70 | + } | ||
| 67 | 71 | ||
| 68 | } | 72 | } |
demoiselle-security-basic/pom.xml
| @@ -22,6 +22,11 @@ | @@ -22,6 +22,11 @@ | ||
| 22 | <groupId>org.demoiselle.jee</groupId> | 22 | <groupId>org.demoiselle.jee</groupId> |
| 23 | <artifactId>demoiselle-security</artifactId> | 23 | <artifactId>demoiselle-security</artifactId> |
| 24 | </dependency> | 24 | </dependency> |
| 25 | + | ||
| 26 | + <dependency> | ||
| 27 | + <groupId>org.demoiselle.jee</groupId> | ||
| 28 | + <artifactId>demoiselle-persistence-jpa</artifactId> | ||
| 29 | + </dependency> | ||
| 25 | 30 | ||
| 26 | </dependencies> | 31 | </dependencies> |
| 27 | </project> | 32 | </project> |
demoiselle-security-basic/src/main/java/org/demoiselle/jee/security/basic/impl/TokensManagerImpl.java
| @@ -5,9 +5,12 @@ | @@ -5,9 +5,12 @@ | ||
| 5 | */ | 5 | */ |
| 6 | package org.demoiselle.jee.security.basic.impl; | 6 | package org.demoiselle.jee.security.basic.impl; |
| 7 | 7 | ||
| 8 | +import java.io.UnsupportedEncodingException; | ||
| 9 | +import java.util.Base64; | ||
| 8 | import java.util.logging.Logger; | 10 | import java.util.logging.Logger; |
| 9 | import javax.enterprise.context.Dependent; | 11 | import javax.enterprise.context.Dependent; |
| 10 | import javax.inject.Inject; | 12 | import javax.inject.Inject; |
| 13 | +import javax.persistence.EntityManager; | ||
| 11 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; | 14 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; |
| 12 | import org.demoiselle.jee.core.interfaces.security.Token; | 15 | import org.demoiselle.jee.core.interfaces.security.Token; |
| 13 | import org.demoiselle.jee.core.interfaces.security.TokensManager; | 16 | import org.demoiselle.jee.core.interfaces.security.TokensManager; |
| @@ -20,34 +23,40 @@ import org.demoiselle.jee.core.interfaces.security.TokensManager; | @@ -20,34 +23,40 @@ import org.demoiselle.jee.core.interfaces.security.TokensManager; | ||
| 20 | public class TokensManagerImpl implements TokensManager { | 23 | public class TokensManagerImpl implements TokensManager { |
| 21 | 24 | ||
| 22 | @Inject | 25 | @Inject |
| 23 | - private Logger logger; | 26 | + private DemoisellePrincipal loggedUser; |
| 24 | 27 | ||
| 25 | @Inject | 28 | @Inject |
| 26 | private Token token; | 29 | private Token token; |
| 27 | 30 | ||
| 28 | @Inject | 31 | @Inject |
| 29 | - private DemoisellePrincipal loggedUser; | 32 | + private Logger logger; |
| 33 | + | ||
| 34 | + @Inject | ||
| 35 | + private EntityManager entityManager; | ||
| 30 | 36 | ||
| 31 | @Override | 37 | @Override |
| 32 | public DemoisellePrincipal getUser() { | 38 | public DemoisellePrincipal getUser() { |
| 33 | - if (loggedUser == null) { | ||
| 34 | - if (token.getKey() != null && !token.getKey().isEmpty()) { | ||
| 35 | - // desfaz o basic | ||
| 36 | - return loggedUser; | ||
| 37 | - } | 39 | + try { |
| 40 | + | ||
| 41 | + byte[] asBytes = Base64.getDecoder().decode(token.getKey()); | ||
| 42 | + String login = new String(asBytes, "utf-8"); | ||
| 43 | + loggedUser = (DemoisellePrincipal) entityManager.createNativeQuery("select * from usuario where usuario = " + login.split(":")[0] + " senha = " + login.split(":")[1]).getResultList().get(0); | ||
| 44 | + | ||
| 45 | + } catch (UnsupportedEncodingException ex) { | ||
| 46 | + logger.severe(ex.getMessage()); | ||
| 38 | } | 47 | } |
| 48 | + | ||
| 39 | return loggedUser; | 49 | return loggedUser; |
| 40 | } | 50 | } |
| 41 | 51 | ||
| 42 | @Override | 52 | @Override |
| 43 | public void setUser(DemoisellePrincipal user) { | 53 | public void setUser(DemoisellePrincipal user) { |
| 44 | - String value = null; | ||
| 45 | - | 54 | + loggedUser = user; |
| 46 | } | 55 | } |
| 47 | 56 | ||
| 48 | @Override | 57 | @Override |
| 49 | public boolean validate() { | 58 | public boolean validate() { |
| 50 | - return true;//(getUser() != null && repo.get(token.getKey()).); | 59 | + return getUser() != null; |
| 51 | } | 60 | } |
| 52 | 61 | ||
| 53 | } | 62 | } |
demoiselle-security-jwt/src/main/java/org/demoiselle/jee/security/jwt/impl/TokensManagerImpl.java
| @@ -5,12 +5,11 @@ | @@ -5,12 +5,11 @@ | ||
| 5 | */ | 5 | */ |
| 6 | package org.demoiselle.jee.security.jwt.impl; | 6 | package org.demoiselle.jee.security.jwt.impl; |
| 7 | 7 | ||
| 8 | -import com.google.gson.Gson; | ||
| 9 | -import java.security.Key; | ||
| 10 | -import java.security.Principal; | ||
| 11 | -import java.util.logging.Level; | 8 | +import java.util.List; |
| 9 | +import java.util.Map; | ||
| 12 | import java.util.logging.Logger; | 10 | import java.util.logging.Logger; |
| 13 | import javax.enterprise.context.Dependent; | 11 | import javax.enterprise.context.Dependent; |
| 12 | +import javax.enterprise.context.RequestScoped; | ||
| 14 | import javax.inject.Inject; | 13 | import javax.inject.Inject; |
| 15 | import javax.servlet.http.HttpServletRequest; | 14 | import javax.servlet.http.HttpServletRequest; |
| 16 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; | 15 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; |
| @@ -36,7 +35,7 @@ public class TokensManagerImpl implements TokensManager { | @@ -36,7 +35,7 @@ public class TokensManagerImpl implements TokensManager { | ||
| 36 | @Inject | 35 | @Inject |
| 37 | private HttpServletRequest httpRequest; | 36 | private HttpServletRequest httpRequest; |
| 38 | 37 | ||
| 39 | - private RsaJsonWebKey rsaJsonWebKey; | 38 | + private static RsaJsonWebKey rsaJsonWebKey; |
| 40 | 39 | ||
| 41 | @Inject | 40 | @Inject |
| 42 | private Logger logger; | 41 | private Logger logger; |
| @@ -48,12 +47,14 @@ public class TokensManagerImpl implements TokensManager { | @@ -48,12 +47,14 @@ public class TokensManagerImpl implements TokensManager { | ||
| 48 | private DemoisellePrincipal loggedUser; | 47 | private DemoisellePrincipal loggedUser; |
| 49 | 48 | ||
| 50 | public TokensManagerImpl() throws JoseException { | 49 | public TokensManagerImpl() throws JoseException { |
| 51 | - RsaJsonWebKey chave = RsaJwkGenerator.generateJwk(2048); | ||
| 52 | - logger.info("Se você quiser usar sua app em cluster, coloque o parametro jwt.key no app.properties e reinicie a aplicacao"); | ||
| 53 | - logger.log(Level.INFO, "jwt.key={0}", chave); | ||
| 54 | - logger.info("Se você não usar esse parametro, a cada reinicialização será gerada uma nova chave privada, isso inviabiliza o uso em cluster "); | ||
| 55 | - rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk((Key) chave); | ||
| 56 | - rsaJsonWebKey.setKeyId("demoiselle-security-jwt"); | 50 | + if (rsaJsonWebKey == null) { |
| 51 | +// RsaJsonWebKey chave = RsaJwkGenerator.generateJwk(2048); | ||
| 52 | +// logger.info("Se você quiser usar sua app em cluster, coloque o parametro jwt.key no app.properties e reinicie a aplicacao"); | ||
| 53 | +// logger.log(Level.INFO, "jwt.key={0}", chave); | ||
| 54 | +// logger.info("Se você não usar esse parametro, a cada reinicialização será gerada uma nova chave privada, isso inviabiliza o uso em cluster "); | ||
| 55 | + rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk(RsaJwkGenerator.generateJwk(2048).getKey()); | ||
| 56 | + rsaJsonWebKey.setKeyId("demoiselle-security-jwt"); | ||
| 57 | + } | ||
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | @Override | 60 | @Override |
| @@ -68,12 +69,18 @@ public class TokensManagerImpl implements TokensManager { | @@ -68,12 +69,18 @@ public class TokensManagerImpl implements TokensManager { | ||
| 68 | .setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key | 69 | .setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key |
| 69 | .build(); // create the JwtConsumer instance | 70 | .build(); // create the JwtConsumer instance |
| 70 | JwtClaims jwtClaims = jwtConsumer.processToClaims(token.getKey()); | 71 | JwtClaims jwtClaims = jwtConsumer.processToClaims(token.getKey()); |
| 71 | - loggedUser = new Gson().fromJson((String) jwtClaims.getClaimValue("user"), DemoisellePrincipal.class); | 72 | + loggedUser.setId((String) jwtClaims.getClaimValue("id")); |
| 73 | + loggedUser.setName((String) jwtClaims.getClaimValue("name")); | ||
| 74 | + loggedUser.setRoles((List) jwtClaims.getClaimValue("roles")); | ||
| 75 | + loggedUser.setPermissions((Map) jwtClaims.getClaimValue("permissions")); | ||
| 76 | + //loggedUser = new Gson().fromJson((String) jwtClaims.getClaimValue("user"), DemoisellePrincipal.class); | ||
| 72 | String ip = httpRequest.getRemoteAddr(); | 77 | String ip = httpRequest.getRemoteAddr(); |
| 73 | if (!ip.equalsIgnoreCase((String) jwtClaims.getClaimValue("ip"))) { | 78 | if (!ip.equalsIgnoreCase((String) jwtClaims.getClaimValue("ip"))) { |
| 74 | return null; | 79 | return null; |
| 75 | } | 80 | } |
| 76 | } catch (InvalidJwtException ex) { | 81 | } catch (InvalidJwtException ex) { |
| 82 | + loggedUser = null; | ||
| 83 | + token.setKey(null); | ||
| 77 | logger.severe(ex.getMessage()); | 84 | logger.severe(ex.getMessage()); |
| 78 | } | 85 | } |
| 79 | } | 86 | } |
| @@ -92,23 +99,27 @@ public class TokensManagerImpl implements TokensManager { | @@ -92,23 +99,27 @@ public class TokensManagerImpl implements TokensManager { | ||
| 92 | claims.setNotBeforeMinutesInThePast(1); | 99 | claims.setNotBeforeMinutesInThePast(1); |
| 93 | 100 | ||
| 94 | claims.setClaim("ip", httpRequest.getRemoteAddr()); | 101 | claims.setClaim("ip", httpRequest.getRemoteAddr()); |
| 95 | - claims.setClaim("user", new Gson().toJson(user)); | 102 | + claims.setClaim("id", (user.getId())); |
| 103 | + claims.setClaim("name", (user.getName())); | ||
| 104 | + claims.setClaim("roles", (user.getRoles())); | ||
| 105 | + claims.setClaim("permissions", (user.getPermissions())); | ||
| 96 | 106 | ||
| 97 | JsonWebSignature jws = new JsonWebSignature(); | 107 | JsonWebSignature jws = new JsonWebSignature(); |
| 98 | jws.setPayload(claims.toJson()); | 108 | jws.setPayload(claims.toJson()); |
| 99 | - jws.setKey(rsaJsonWebKey.getPrivateKey()); | 109 | + jws.setKey(rsaJsonWebKey.getKey()); |
| 100 | jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId()); | 110 | jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId()); |
| 101 | - jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); | 111 | + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA512); |
| 102 | token.setKey(jws.getCompactSerialization()); | 112 | token.setKey(jws.getCompactSerialization()); |
| 103 | } catch (JoseException ex) { | 113 | } catch (JoseException ex) { |
| 104 | - logger.severe(ex.getMessage()); | 114 | + ex.printStackTrace(); |
| 115 | + // logger.severe(ex.getMessage()); | ||
| 105 | } | 116 | } |
| 106 | 117 | ||
| 107 | } | 118 | } |
| 108 | 119 | ||
| 109 | @Override | 120 | @Override |
| 110 | public boolean validate() { | 121 | public boolean validate() { |
| 111 | - return true; | 122 | + return getUser() != null; |
| 112 | } | 123 | } |
| 113 | 124 | ||
| 114 | } | 125 | } |
demoiselle-security-token/src/main/java/org/demoiselle/jee/security/token/impl/TokensManagerImpl.java
| @@ -5,7 +5,8 @@ | @@ -5,7 +5,8 @@ | ||
| 5 | */ | 5 | */ |
| 6 | package org.demoiselle.jee.security.token.impl; | 6 | package org.demoiselle.jee.security.token.impl; |
| 7 | 7 | ||
| 8 | -import java.security.Principal; | 8 | +import java.util.Iterator; |
| 9 | +import java.util.Map; | ||
| 9 | import java.util.UUID; | 10 | import java.util.UUID; |
| 10 | import java.util.concurrent.ConcurrentHashMap; | 11 | import java.util.concurrent.ConcurrentHashMap; |
| 11 | import java.util.logging.Logger; | 12 | import java.util.logging.Logger; |
| @@ -20,7 +21,7 @@ import org.demoiselle.jee.core.interfaces.security.TokensManager; | @@ -20,7 +21,7 @@ import org.demoiselle.jee.core.interfaces.security.TokensManager; | ||
| 20 | * | 21 | * |
| 21 | * @author 70744416353 | 22 | * @author 70744416353 |
| 22 | */ | 23 | */ |
| 23 | -@RequestScoped | 24 | +@Dependent |
| 24 | public class TokensManagerImpl implements TokensManager { | 25 | public class TokensManagerImpl implements TokensManager { |
| 25 | 26 | ||
| 26 | private final static ConcurrentHashMap<String, DemoisellePrincipal> repo = new ConcurrentHashMap<>(); | 27 | private final static ConcurrentHashMap<String, DemoisellePrincipal> repo = new ConcurrentHashMap<>(); |
| @@ -45,13 +46,17 @@ public class TokensManagerImpl implements TokensManager { | @@ -45,13 +46,17 @@ public class TokensManagerImpl implements TokensManager { | ||
| 45 | String value = UUID.randomUUID().toString(); | 46 | String value = UUID.randomUUID().toString(); |
| 46 | repo.put(value, user); | 47 | repo.put(value, user); |
| 47 | token.setKey(value); | 48 | token.setKey(value); |
| 48 | - token.setType("Token"); | 49 | + } else { |
| 50 | + repo.entrySet().parallelStream().filter((e) -> (user.equals(e.getValue()))).forEach((e) -> { | ||
| 51 | + token.setKey((String) e.getKey()); | ||
| 52 | + }); | ||
| 49 | } | 53 | } |
| 54 | + token.setType("Token"); | ||
| 50 | } | 55 | } |
| 51 | 56 | ||
| 52 | @Override | 57 | @Override |
| 53 | public boolean validate() { | 58 | public boolean validate() { |
| 54 | - return true;//(getUser() != null && repo.get(token.getKey()).); | 59 | + return getUser() != null; |
| 55 | } | 60 | } |
| 56 | 61 | ||
| 57 | } | 62 | } |
demoiselle-security/pom.xml
| @@ -23,6 +23,10 @@ | @@ -23,6 +23,10 @@ | ||
| 23 | <groupId>org.demoiselle.jee</groupId> | 23 | <groupId>org.demoiselle.jee</groupId> |
| 24 | <artifactId>demoiselle-core</artifactId> | 24 | <artifactId>demoiselle-core</artifactId> |
| 25 | </dependency> | 25 | </dependency> |
| 26 | - | 26 | + |
| 27 | + <dependency> | ||
| 28 | + <groupId>org.demoiselle.jee</groupId> | ||
| 29 | + <artifactId>demoiselle-rest</artifactId> | ||
| 30 | + </dependency> | ||
| 27 | </dependencies> | 31 | </dependencies> |
| 28 | </project> | 32 | </project> |
demoiselle-security/src/main/java/org/demoiselle/jee/security/exception/DemoiselleSecurityException.java
| @@ -8,30 +8,31 @@ package org.demoiselle.jee.security.exception; | @@ -8,30 +8,31 @@ package org.demoiselle.jee.security.exception; | ||
| 8 | 8 | ||
| 9 | import java.util.HashMap; | 9 | import java.util.HashMap; |
| 10 | 10 | ||
| 11 | -import org.demoiselle.jee.core.exception.DemoiselleException; | 11 | +import org.demoiselle.jee.ws.jaxrs.exception.DemoiselleRESTException; |
| 12 | 12 | ||
| 13 | -public class DemoiselleSecurityException extends DemoiselleException { | 13 | +public class DemoiselleSecurityException extends DemoiselleRESTException { |
| 14 | 14 | ||
| 15 | - private static final long serialVersionUID = 519965615171844237L; | 15 | + private static final long serialVersionUID = 519965615171844237L; |
| 16 | 16 | ||
| 17 | - private HashMap<String, String> messages = new HashMap<String, String>(); | 17 | + private HashMap<String, String> messages = new HashMap<String, String>(); |
| 18 | 18 | ||
| 19 | - private int statusCode; | 19 | + private int statusCode; |
| 20 | 20 | ||
| 21 | - public DemoiselleSecurityException(String string) { | ||
| 22 | - super(string); | ||
| 23 | - } | 21 | + public DemoiselleSecurityException(String string) { |
| 22 | + super(string); | ||
| 23 | + this.statusCode = 401; | ||
| 24 | + } | ||
| 24 | 25 | ||
| 25 | - public int getStatusCode() { | ||
| 26 | - return statusCode; | ||
| 27 | - } | 26 | + public int getStatusCode() { |
| 27 | + return statusCode; | ||
| 28 | + } | ||
| 28 | 29 | ||
| 29 | - public void addMessage(String field, String msg) { | ||
| 30 | - this.statusCode = 422; | ||
| 31 | - messages.put(field, msg); | ||
| 32 | - } | 30 | + public void addMessage(String field, String msg) { |
| 33 | 31 | ||
| 34 | - public HashMap<String, String> getMessages() { | ||
| 35 | - return messages; | ||
| 36 | - } | 32 | + messages.put(field, msg); |
| 33 | + } | ||
| 34 | + | ||
| 35 | + public HashMap<String, String> getMessages() { | ||
| 36 | + return messages; | ||
| 37 | + } | ||
| 37 | } | 38 | } |
demoiselle-security/src/main/java/org/demoiselle/jee/security/exception/NotLoggedInException.java
| @@ -13,7 +13,7 @@ package org.demoiselle.jee.security.exception; | @@ -13,7 +13,7 @@ package org.demoiselle.jee.security.exception; | ||
| 13 | * | 13 | * |
| 14 | * @author SERPRO | 14 | * @author SERPRO |
| 15 | */ | 15 | */ |
| 16 | -public class NotLoggedInException extends AuthenticationException { | 16 | +public class NotLoggedInException extends DemoiselleSecurityException { |
| 17 | 17 | ||
| 18 | private static final long serialVersionUID = 1L; | 18 | private static final long serialVersionUID = 1L; |
| 19 | 19 | ||
| @@ -27,4 +27,6 @@ public class NotLoggedInException extends AuthenticationException { | @@ -27,4 +27,6 @@ public class NotLoggedInException extends AuthenticationException { | ||
| 27 | public NotLoggedInException(String message) { | 27 | public NotLoggedInException(String message) { |
| 28 | super(message); | 28 | super(message); |
| 29 | } | 29 | } |
| 30 | + | ||
| 31 | + | ||
| 30 | } | 32 | } |
demoiselle-security/src/main/java/org/demoiselle/jee/security/impl/DemoisellePrincipalImpl.java
0 → 100644
| @@ -0,0 +1,97 @@ | @@ -0,0 +1,97 @@ | ||
| 1 | +/* | ||
| 2 | + * Demoiselle Framework | ||
| 3 | + * | ||
| 4 | + * License: GNU Lesser General Public License (LGPL), version 3 or later. | ||
| 5 | + * See the lgpl.txt file in the root directory or <https://www.gnu.org/licenses/lgpl.html>. | ||
| 6 | + */ | ||
| 7 | +package org.demoiselle.jee.security.impl; | ||
| 8 | + | ||
| 9 | +import java.util.List; | ||
| 10 | +import java.util.Map; | ||
| 11 | +import java.util.Objects; | ||
| 12 | +import javax.enterprise.context.RequestScoped; | ||
| 13 | +import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * | ||
| 17 | + * @author 70744416353 | ||
| 18 | + */ | ||
| 19 | +@RequestScoped | ||
| 20 | +public class DemoisellePrincipalImpl implements DemoisellePrincipal { | ||
| 21 | + | ||
| 22 | + private String id; | ||
| 23 | + private String name; | ||
| 24 | + private List<String> roles; | ||
| 25 | + private Map<String, String> permissions; | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public String getId() { | ||
| 29 | + return id; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public void setId(String id) { | ||
| 34 | + this.id = id; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public String getName() { | ||
| 39 | + return name; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public void setName(String name) { | ||
| 44 | + this.name = name; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public List<String> getRoles() { | ||
| 49 | + return roles; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + public void setRoles(List<String> roles) { | ||
| 54 | + this.roles = roles; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public Map<String, String> getPermissions() { | ||
| 59 | + return permissions; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @Override | ||
| 63 | + public void setPermissions(Map<String, String> permissions) { | ||
| 64 | + this.permissions = permissions; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @Override | ||
| 68 | + public int hashCode() { | ||
| 69 | + int hash = 7; | ||
| 70 | + hash = 37 * hash + Objects.hashCode(this.id); | ||
| 71 | + return hash; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @Override | ||
| 75 | + public boolean equals(Object obj) { | ||
| 76 | + if (this == obj) { | ||
| 77 | + return true; | ||
| 78 | + } | ||
| 79 | + if (obj == null) { | ||
| 80 | + return false; | ||
| 81 | + } | ||
| 82 | + if (getClass() != obj.getClass()) { | ||
| 83 | + return false; | ||
| 84 | + } | ||
| 85 | + final DemoisellePrincipalImpl other = (DemoisellePrincipalImpl) obj; | ||
| 86 | + if (!Objects.equals(this.id, other.id)) { | ||
| 87 | + return false; | ||
| 88 | + } | ||
| 89 | + return true; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @Override | ||
| 93 | + public String toString() { | ||
| 94 | + return "DemoisellePrincipalImpl{" + "id=" + id + ", name=" + name + ", roles=" + roles + ", permissions=" + permissions + '}'; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | +} |
demoiselle-security/src/main/java/org/demoiselle/jee/security/impl/SecurityContextImpl.java
| @@ -6,15 +6,17 @@ | @@ -6,15 +6,17 @@ | ||
| 6 | */ | 6 | */ |
| 7 | package org.demoiselle.jee.security.impl; | 7 | package org.demoiselle.jee.security.impl; |
| 8 | 8 | ||
| 9 | +import java.util.Iterator; | ||
| 10 | +import java.util.Map; | ||
| 11 | +import java.util.stream.Collectors; | ||
| 9 | import javax.enterprise.context.Dependent; | 12 | import javax.enterprise.context.Dependent; |
| 10 | import javax.inject.Inject; | 13 | import javax.inject.Inject; |
| 11 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; | 14 | import org.demoiselle.jee.core.interfaces.security.DemoisellePrincipal; |
| 12 | 15 | ||
| 13 | -import org.demoiselle.jee.core.util.ResourceBundle; | ||
| 14 | - | ||
| 15 | import org.demoiselle.jee.security.exception.NotLoggedInException; | 16 | import org.demoiselle.jee.security.exception.NotLoggedInException; |
| 16 | import org.demoiselle.jee.core.interfaces.security.SecurityContext; | 17 | import org.demoiselle.jee.core.interfaces.security.SecurityContext; |
| 17 | import org.demoiselle.jee.core.interfaces.security.TokensManager; | 18 | import org.demoiselle.jee.core.interfaces.security.TokensManager; |
| 19 | +import org.demoiselle.jee.security.message.DemoiselleSecurityMessages; | ||
| 18 | 20 | ||
| 19 | /** | 21 | /** |
| 20 | * <p> | 22 | * <p> |
| @@ -32,7 +34,7 @@ public class SecurityContextImpl implements SecurityContext { | @@ -32,7 +34,7 @@ public class SecurityContextImpl implements SecurityContext { | ||
| 32 | private TokensManager tm; | 34 | private TokensManager tm; |
| 33 | 35 | ||
| 34 | @Inject | 36 | @Inject |
| 35 | - private ResourceBundle bundle; | 37 | + private DemoiselleSecurityMessages bundle; |
| 36 | 38 | ||
| 37 | /** | 39 | /** |
| 38 | * @see org.demoiselle.security.SecurityContext#hasPermission(String, | 40 | * @see org.demoiselle.security.SecurityContext#hasPermission(String, |
| @@ -40,9 +42,11 @@ public class SecurityContextImpl implements SecurityContext { | @@ -40,9 +42,11 @@ public class SecurityContextImpl implements SecurityContext { | ||
| 40 | */ | 42 | */ |
| 41 | @Override | 43 | @Override |
| 42 | public boolean hasPermission(String resource, String operation) { | 44 | public boolean hasPermission(String resource, String operation) { |
| 43 | - boolean result = true; | ||
| 44 | - | ||
| 45 | - return result; | 45 | + return (tm.getUser().getPermissions().entrySet() |
| 46 | + .stream() | ||
| 47 | + .filter(p -> p.getKey().equalsIgnoreCase(resource)) | ||
| 48 | + .filter(p -> p.getValue().equalsIgnoreCase(operation)) | ||
| 49 | + .count() > 0); | ||
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | /** | 52 | /** |
| @@ -50,9 +54,7 @@ public class SecurityContextImpl implements SecurityContext { | @@ -50,9 +54,7 @@ public class SecurityContextImpl implements SecurityContext { | ||
| 50 | */ | 54 | */ |
| 51 | @Override | 55 | @Override |
| 52 | public boolean hasRole(String role) { | 56 | public boolean hasRole(String role) { |
| 53 | - boolean result = true; | ||
| 54 | - | ||
| 55 | - return result; | 57 | + return (tm.getUser().getRoles().parallelStream().filter(p -> p.equals(role)).count() > 0); |
| 56 | } | 58 | } |
| 57 | 59 | ||
| 58 | /** | 60 | /** |
| @@ -66,7 +68,7 @@ public class SecurityContextImpl implements SecurityContext { | @@ -66,7 +68,7 @@ public class SecurityContextImpl implements SecurityContext { | ||
| 66 | @Override | 68 | @Override |
| 67 | public void checkLoggedIn() throws NotLoggedInException { | 69 | public void checkLoggedIn() throws NotLoggedInException { |
| 68 | if (!isLoggedIn()) { | 70 | if (!isLoggedIn()) { |
| 69 | - throw new NotLoggedInException(bundle.getString("user-not-authenticated")); | 71 | + throw new NotLoggedInException(bundle.userNotAuthenticated()); |
| 70 | } | 72 | } |
| 71 | } | 73 | } |
| 72 | 74 |
demoiselle-security/src/main/java/org/demoiselle/jee/security/impl/TokenImpl.java
| @@ -6,13 +6,14 @@ | @@ -6,13 +6,14 @@ | ||
| 6 | package org.demoiselle.jee.security.impl; | 6 | package org.demoiselle.jee.security.impl; |
| 7 | 7 | ||
| 8 | import javax.enterprise.context.Dependent; | 8 | import javax.enterprise.context.Dependent; |
| 9 | +import javax.enterprise.context.RequestScoped; | ||
| 9 | import org.demoiselle.jee.core.interfaces.security.Token; | 10 | import org.demoiselle.jee.core.interfaces.security.Token; |
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| 12 | * | 13 | * |
| 13 | * @author 70744416353 | 14 | * @author 70744416353 |
| 14 | */ | 15 | */ |
| 15 | -@Dependent | 16 | +@RequestScoped |
| 16 | public class TokenImpl implements Token { | 17 | public class TokenImpl implements Token { |
| 17 | 18 | ||
| 18 | private String key; | 19 | private String key; |
demoiselle-security/src/main/java/org/demoiselle/jee/security/message/DemoiselleSecurityMessages.java
0 → 100644
| @@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
| 1 | +/* | ||
| 2 | + * Demoiselle Framework | ||
| 3 | + * | ||
| 4 | + * License: GNU Lesser General Public License (LGPL), version 3 or later. | ||
| 5 | + * See the lgpl.txt file in the root directory or <https://www.gnu.org/licenses/lgpl.html>. | ||
| 6 | + */ | ||
| 7 | +package org.demoiselle.jee.security.message; | ||
| 8 | + | ||
| 9 | +import org.apache.deltaspike.core.api.message.MessageBundle; | ||
| 10 | +import org.apache.deltaspike.core.api.message.MessageTemplate; | ||
| 11 | + | ||
| 12 | +@MessageBundle | ||
| 13 | +public interface DemoiselleSecurityMessages { | ||
| 14 | + | ||
| 15 | + @MessageTemplate("{user-not-authenticated}") | ||
| 16 | + String userNotAuthenticated(); | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +} | ||
| 0 | \ No newline at end of file | 20 | \ No newline at end of file |
demoiselle-security/src/main/resources/messages.properties
| @@ -1,12 +0,0 @@ | @@ -1,12 +0,0 @@ | ||
| 1 | -adding-message-to-context=Adicionando uma mensagem no contexto: [{0}] | ||
| 2 | -access-checking=Verificando permiss\u00e3o do usu\u00e1rio {0} para executar a a\u00e7\u00e3o {1} no recurso {2} | ||
| 3 | -access-allowed=O usu\u00e1rio {0} acessou o recurso {2} com a a\u00e7\u00e3o {1} | ||
| 4 | -access-denied=O usu\u00e1rio {0} n\u00e3o possui permiss\u00e3o para executar a a\u00e7\u00e3o {1} no recurso {2} | ||
| 5 | -access-denied-ui=Voc\u00ea n\u00e3o est\u00e1 autorizado a executar a a\u00e7\u00e3o {1} no recurso {0} | ||
| 6 | -authorizer-not-defined=Nenhuma regra de resolu\u00e7\u00e3o de permiss\u00f5es foi definida. Para utilizar @{0} \u00e9 preciso definir a propriedade frameworkdemoiselle.security.authorizer.class como regra de resolu\u00e7\u00e3o de permiss\u00f5es desejada no arquivo demoiselle.properties. | ||
| 7 | -user-not-authenticated=Usu\u00e1rio n\u00e3o autenticado | ||
| 8 | -invalid-credentials=Usu\u00e1rio ou senha inv\u00e1lidos | ||
| 9 | -has-role-verification=Verificando se o usu\u00e1rio {0} possui a(s) role(s)\: {1} | ||
| 10 | -does-not-have-role=Usu\u00e1rio {0} n\u00e3o possui a(s) role(s)\: {1} | ||
| 11 | -does-not-have-role-ui=Para acessar este recurso \u00e9 necess\u00e1rio ser {0} | ||
| 12 | -user-has-role=Usu\u00e1rio {0} possui a(s) role(s)\: {1} | ||
| 13 | \ No newline at end of file | 0 | \ No newline at end of file |
demoiselle-security/src/main/resources/org/demoiselle/jee/security/message/DemoiselleSecurityMessages.properties
0 → 100644
| @@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
| 1 | +adding-message-to-context=Adicionando uma mensagem no contexto: [{0}] | ||
| 2 | +access-checking=Verificando permiss\u00e3o do usu\u00e1rio {0} para executar a a\u00e7\u00e3o {1} no recurso {2} | ||
| 3 | +access-allowed=O usu\u00e1rio {0} acessou o recurso {2} com a a\u00e7\u00e3o {1} | ||
| 4 | +access-denied=O usu\u00e1rio {0} n\u00e3o possui permiss\u00e3o para executar a a\u00e7\u00e3o {1} no recurso {2} | ||
| 5 | +access-denied-ui=Voc\u00ea n\u00e3o est\u00e1 autorizado a executar a a\u00e7\u00e3o {1} no recurso {0} | ||
| 6 | +authorizer-not-defined=Nenhuma regra de resolu\u00e7\u00e3o de permiss\u00f5es foi definida. Para utilizar @{0} \u00e9 preciso definir a propriedade frameworkdemoiselle.security.authorizer.class como regra de resolu\u00e7\u00e3o de permiss\u00f5es desejada no arquivo demoiselle.properties. | ||
| 7 | +user-not-authenticated=Usu\u00e1rio n\u00e3o autenticado | ||
| 8 | +invalid-credentials=Usu\u00e1rio ou senha inv\u00e1lidos | ||
| 9 | +has-role-verification=Verificando se o usu\u00e1rio {0} possui a(s) role(s)\: {1} | ||
| 10 | +does-not-have-role=Usu\u00e1rio {0} n\u00e3o possui a(s) role(s)\: {1} | ||
| 11 | +does-not-have-role-ui=Para acessar este recurso \u00e9 necess\u00e1rio ser {0} | ||
| 12 | +user-has-role=Usu\u00e1rio {0} possui a(s) role(s)\: {1} | ||
| 0 | \ No newline at end of file | 13 | \ No newline at end of file |