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,6 +11,7 @@ | ||
11 | <maven.compiler.target>1.8</maven.compiler.target> | 11 | <maven.compiler.target>1.8</maven.compiler.target> |
12 | </properties> | 12 | </properties> |
13 | <dependencies> | 13 | <dependencies> |
14 | + | ||
14 | <dependency> | 15 | <dependency> |
15 | <groupId>${project.groupId}</groupId> | 16 | <groupId>${project.groupId}</groupId> |
16 | <artifactId>demoiselle-core</artifactId> | 17 | <artifactId>demoiselle-core</artifactId> |
@@ -29,5 +30,18 @@ | @@ -29,5 +30,18 @@ | ||
29 | <version>${project.version}</version> | 30 | <version>${project.version}</version> |
30 | </dependency> | 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 | </dependencies> | 46 | </dependencies> |
33 | </project> | 47 | </project> |
jwt/src/main/java/org/demoiselle/jee/security/jwt/impl/SecurityContextImpl.java
0 → 100644
@@ -0,0 +1,123 @@ | @@ -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 @@ | @@ -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 | +} |
pom.xml
@@ -31,6 +31,7 @@ | @@ -31,6 +31,7 @@ | ||
31 | <!--<module>swagger</module>--> | 31 | <!--<module>swagger</module>--> |
32 | <module>security</module> | 32 | <module>security</module> |
33 | <module>basic</module> | 33 | <module>basic</module> |
34 | + <module>jwt</module> | ||
34 | </modules> | 35 | </modules> |
35 | 36 | ||
36 | <dependencyManagement> | 37 | <dependencyManagement> |