Commit b1a280739c057b2aa569350d380f7d01f1bf8eb8
1 parent
fcb6b857
Segurança
Showing
6 changed files
with
246 additions
and
0 deletions
Show diff stats
jwt/pom.xml
| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | <maven.compiler.target>1.8</maven.compiler.target> |
| 12 | 12 | </properties> |
| 13 | 13 | <dependencies> |
| 14 | + | |
| 14 | 15 | <dependency> |
| 15 | 16 | <groupId>${project.groupId}</groupId> |
| 16 | 17 | <artifactId>demoiselle-core</artifactId> |
| ... | ... | @@ -29,5 +30,18 @@ |
| 29 | 30 | <version>${project.version}</version> |
| 30 | 31 | </dependency> |
| 31 | 32 | |
| 33 | + <dependency> | |
| 34 | + <groupId>org.bitbucket.b_c</groupId> | |
| 35 | + <artifactId>jose4j</artifactId> | |
| 36 | + <version>0.4.1</version> | |
| 37 | + </dependency> | |
| 38 | + | |
| 39 | + <dependency> | |
| 40 | + <groupId>com.google.code.gson</groupId> | |
| 41 | + <artifactId>gson</artifactId> | |
| 42 | + <version>2.2.2</version> | |
| 43 | + <scope>compile</scope> | |
| 44 | + </dependency> | |
| 45 | + | |
| 32 | 46 | </dependencies> |
| 33 | 47 | </project> | ... | ... |
jwt/src/main/java/org/demoiselle/jee/security/jwt/impl/SecurityContextImpl.java
0 → 100644
| ... | ... | @@ -0,0 +1,123 @@ |
| 1 | +package org.demoiselle.jee.security.jwt.impl; | |
| 2 | + | |
| 3 | +import org.demoiselle.jee.security.Token; | |
| 4 | +import javax.enterprise.context.Dependent; | |
| 5 | +import java.security.Principal; | |
| 6 | +import java.util.Map; | |
| 7 | +import java.util.Set; | |
| 8 | +import javax.inject.Inject; | |
| 9 | +import org.demoiselle.jee.core.util.ResourceBundle; | |
| 10 | +import org.demoiselle.jee.security.interfaces.SecurityContext; | |
| 11 | +import org.demoiselle.jee.security.exception.NotLoggedInException; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * <p> | |
| 15 | + * This is the default implementation of {@link SecurityContext} interface. | |
| 16 | + * </p> | |
| 17 | + * | |
| 18 | + * @author SERPRO | |
| 19 | + */ | |
| 20 | +@Dependent | |
| 21 | +public class SecurityContextImpl implements SecurityContext { | |
| 22 | + | |
| 23 | + private static final long serialVersionUID = 1L; | |
| 24 | + | |
| 25 | + @Inject | |
| 26 | + private TokensManager tm; | |
| 27 | + | |
| 28 | + @Inject | |
| 29 | + private Token token; | |
| 30 | + | |
| 31 | + @Inject | |
| 32 | + private ResourceBundle bundle; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * @see org.demoiselle.security.SecurityContext#hasPermission(String, | |
| 36 | + * String) | |
| 37 | + */ | |
| 38 | + @Override | |
| 39 | + public boolean hasPermission(String resource, String operation) { | |
| 40 | + boolean result = true; | |
| 41 | + | |
| 42 | + return result; | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * @see org.demoiselle.security.SecurityContext#hasRole(String) | |
| 47 | + */ | |
| 48 | + @Override | |
| 49 | + public boolean hasRole(String role) { | |
| 50 | + boolean result = true; | |
| 51 | + | |
| 52 | + return result; | |
| 53 | + } | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * @see org.demoiselle.security.SecurityContext#isLoggedIn() | |
| 57 | + */ | |
| 58 | + @Override | |
| 59 | + public boolean isLoggedIn() { | |
| 60 | + return getUser() != null; | |
| 61 | + } | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * @see org.demoiselle.security.SecurityContext#getUser() | |
| 65 | + */ | |
| 66 | + @Override | |
| 67 | + public Principal getUser() { | |
| 68 | + if (token.getKey() != null && !token.getKey().isEmpty()) { | |
| 69 | + return tm.getUser(token.getKey()); | |
| 70 | + } | |
| 71 | + return token.getPrincipal(); | |
| 72 | + } | |
| 73 | + | |
| 74 | + public void checkLoggedIn() throws NotLoggedInException { | |
| 75 | + if (!isLoggedIn()) { | |
| 76 | + throw new NotLoggedInException(bundle.getString("user-not-authenticated")); | |
| 77 | + } | |
| 78 | + } | |
| 79 | + | |
| 80 | + @Override | |
| 81 | + public void setRoles(Set<String> roles) { | |
| 82 | + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. | |
| 83 | + } | |
| 84 | + | |
| 85 | + @Override | |
| 86 | + public void setPermission(Map<String, String> permissions) { | |
| 87 | + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. | |
| 88 | + } | |
| 89 | + | |
| 90 | + @Override | |
| 91 | + public Set<String> getResources(String operation) { | |
| 92 | + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public Set<String> getOperations(String resources) { | |
| 97 | + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public void setUser(Principal principal) { | |
| 102 | + token.setKey(tm.getToken(principal)); | |
| 103 | + token.setPrincipal(principal); | |
| 104 | + } | |
| 105 | + | |
| 106 | + @Override | |
| 107 | + public String getToken() { | |
| 108 | + if (token.getKey() != null && token.getKey().isEmpty()) { | |
| 109 | + token.setKey(tm.getToken(token.getPrincipal())); | |
| 110 | + } | |
| 111 | + return token.getKey(); | |
| 112 | + } | |
| 113 | + | |
| 114 | + @Override | |
| 115 | + public void setToken(String chave) { | |
| 116 | + token.setPrincipal(tm.getUser(chave)); | |
| 117 | + if (token.getPrincipal() == null) { | |
| 118 | + throw new NotLoggedInException(bundle.getString("user-not-authenticated")); | |
| 119 | + } | |
| 120 | + token.setKey(chave); | |
| 121 | + } | |
| 122 | + | |
| 123 | +} | ... | ... |
jwt/src/main/java/org/demoiselle/jee/security/jwt/impl/TokensManager.java
0 → 100644
| ... | ... | @@ -0,0 +1,106 @@ |
| 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 com.google.gson.Gson; | |
| 9 | +import java.security.Key; | |
| 10 | +import java.security.Principal; | |
| 11 | +import java.util.Map; | |
| 12 | +import java.util.UUID; | |
| 13 | +import java.util.logging.Level; | |
| 14 | +import java.util.logging.Logger; | |
| 15 | +import javax.annotation.PostConstruct; | |
| 16 | +import javax.enterprise.context.RequestScoped; | |
| 17 | +import javax.inject.Inject; | |
| 18 | +import javax.servlet.http.HttpServletRequest; | |
| 19 | +import javax.ws.rs.container.PreMatching; | |
| 20 | +import org.jose4j.jwk.RsaJsonWebKey; | |
| 21 | +import org.jose4j.jwk.RsaJwkGenerator; | |
| 22 | +import org.jose4j.jws.AlgorithmIdentifiers; | |
| 23 | +import org.jose4j.jws.JsonWebSignature; | |
| 24 | +import org.jose4j.jwt.JwtClaims; | |
| 25 | +import org.jose4j.jwt.consumer.InvalidJwtException; | |
| 26 | +import org.jose4j.jwt.consumer.JwtConsumer; | |
| 27 | +import org.jose4j.jwt.consumer.JwtConsumerBuilder; | |
| 28 | +import org.jose4j.lang.JoseException; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * | |
| 32 | + * @author 70744416353 | |
| 33 | + */ | |
| 34 | +@RequestScoped | |
| 35 | +public class TokensManager { | |
| 36 | + | |
| 37 | + @Inject | |
| 38 | + private HttpServletRequest httpRequest; | |
| 39 | + | |
| 40 | + private RsaJsonWebKey rsaJsonWebKey; | |
| 41 | + | |
| 42 | + @Inject | |
| 43 | + private Logger logger; | |
| 44 | + | |
| 45 | + public void TokensManager() throws JoseException { | |
| 46 | + RsaJsonWebKey chave = RsaJwkGenerator.generateJwk(2048); | |
| 47 | + logger.info("Se você quiser usar sua app em cluster, coloque o parametro jwt.key no app.properties e reinicie a aplicacao"); | |
| 48 | + logger.log(Level.INFO, "jwt.key={0}", chave); | |
| 49 | + 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 "); | |
| 50 | + rsaJsonWebKey = (RsaJsonWebKey) RsaJsonWebKey.Factory.newPublicJwk((Key) chave); | |
| 51 | + rsaJsonWebKey.setKeyId("demoiselle-security-jwt"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + public Principal getUser(String jwt) { | |
| 55 | + Principal usuario = null; | |
| 56 | + if (jwt != null && !jwt.isEmpty()) { | |
| 57 | + JwtConsumer jwtConsumer = new JwtConsumerBuilder() | |
| 58 | + .setRequireExpirationTime() // the JWT must have an expiration time | |
| 59 | + .setAllowedClockSkewInSeconds(60) // allow some leeway in validating time based claims to account for clock skew | |
| 60 | + .setExpectedIssuer("demoiselle") // whom the JWT needs to have been issued by | |
| 61 | + .setExpectedAudience("demoiselle") // to whom the JWT is intended for | |
| 62 | + .setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key | |
| 63 | + .build(); // create the JwtConsumer instance | |
| 64 | + | |
| 65 | + try { | |
| 66 | + JwtClaims jwtClaims = jwtConsumer.processToClaims(jwt); | |
| 67 | + usuario = new Gson().fromJson((String) jwtClaims.getClaimValue("user"), Principal.class); | |
| 68 | + | |
| 69 | + String ip = httpRequest.getRemoteAddr(); | |
| 70 | + if (!ip.equalsIgnoreCase((String) jwtClaims.getClaimValue("ip"))) { | |
| 71 | + usuario = null; | |
| 72 | + } | |
| 73 | + } catch (InvalidJwtException e) { | |
| 74 | + //Logger.getLogger(TokenRepository.class.getName()).log(Level.SEVERE, null, e); | |
| 75 | + } | |
| 76 | + } | |
| 77 | + return usuario; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public String getToken(Principal user) { | |
| 81 | + try { | |
| 82 | + JwtClaims claims = new JwtClaims(); | |
| 83 | + claims.setIssuer("demoiselle"); | |
| 84 | + claims.setAudience("demoiselle"); | |
| 85 | + claims.setExpirationTimeMinutesInTheFuture(720); | |
| 86 | + claims.setGeneratedJwtId(); | |
| 87 | + claims.setIssuedAtToNow(); | |
| 88 | + claims.setNotBeforeMinutesInThePast(1); | |
| 89 | + | |
| 90 | + claims.setClaim("ip", httpRequest.getRemoteAddr()); | |
| 91 | + claims.setClaim("user", new Gson().toJson(user)); | |
| 92 | + | |
| 93 | + JsonWebSignature jws = new JsonWebSignature(); | |
| 94 | + jws.setPayload(claims.toJson()); | |
| 95 | + jws.setKey(rsaJsonWebKey.getPrivateKey()); | |
| 96 | + jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId()); | |
| 97 | + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); | |
| 98 | + return jws.getCompactSerialization(); | |
| 99 | + } catch (JoseException ex) { | |
| 100 | + logger.severe(ex.getMessage()); | |
| 101 | + } | |
| 102 | + return null; | |
| 103 | + | |
| 104 | + } | |
| 105 | + | |
| 106 | +} | ... | ... |