Commit b1a280739c057b2aa569350d380f7d01f1bf8eb8

Authored by PauloGladson
1 parent fcb6b857

Segurança

@@ -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 +}
jwt/src/main/resources/demoiselle.properties 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +user-not-authenticated
0 \ No newline at end of file 2 \ No newline at end of file
jwt/src/main/resources/messages.properties 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +tipo-seguranca=basic
0 \ No newline at end of file 2 \ No newline at end of file
@@ -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>