diff --git "a/Criar Aplica\303\247\303\243o com autentica\303\247\303\243o via Token .pdf" "b/Criar Aplica\303\247\303\243o com autentica\303\247\303\243o via Token .pdf"
new file mode 100644
index 0000000..cb7de45
Binary files /dev/null and "b/Criar Aplica\303\247\303\243o com autentica\303\247\303\243o via Token .pdf" differ
diff --git a/exemplos/02-1-seguranca-jwt/src/main/resources/application-dev.yaml b/exemplos/02-1-seguranca-jwt/src/main/resources/application-dev.yaml
index 05c263f..c9715e8 100644
--- a/exemplos/02-1-seguranca-jwt/src/main/resources/application-dev.yaml
+++ b/exemplos/02-1-seguranca-jwt/src/main/resources/application-dev.yaml
@@ -1,8 +1,8 @@
spring:
datasource:
- url: jdbc:postgresql://localhost:5432/pweb2
+ url: jdbc:postgresql://localhost:5433/pweb2-jwt
username: postgres
- password: secret
+ password: 1327
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
diff --git a/exemplos/02-seguranca/pom.xml b/exemplos/02-seguranca/pom.xml
index 7c0b5df..8254ede 100644
--- a/exemplos/02-seguranca/pom.xml
+++ b/exemplos/02-seguranca/pom.xml
@@ -15,7 +15,7 @@
Demo project for Spring Security
- 1.8
+ 11
@@ -55,6 +55,23 @@
postgresql
42.2.8
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.10.5
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.10.5
+ runtime
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.10.5
+ runtime
+
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/ApplicationConfig.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/ApplicationConfig.java
index bc36b99..427d18d 100644
--- a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/ApplicationConfig.java
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/ApplicationConfig.java
@@ -1,8 +1,7 @@
package br.com.ifpb.pweb2.securitydemo.config;
import lombok.Data;
-import lombok.Getter;
-import lombok.Setter;
+
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@@ -13,7 +12,7 @@ public class ApplicationConfig {
private AutenticacaoPadrao autenticacaoPadrao = new AutenticacaoPadrao();
- private enum TipoAutenticacao { MEMORIA, BANCO };
+ private enum TipoAutenticacao { MEMORIA, BANCO }
@Data
public class AutenticacaoPadrao {
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/SecurityConfig.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/SecurityConfig.java
new file mode 100644
index 0000000..7356235
--- /dev/null
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/SecurityConfig.java
@@ -0,0 +1,18 @@
+package br.com.ifpb.pweb2.securitydemo.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix="security")
+@Data
+public class SecurityConfig {
+ private String authLoginUrl;
+ private String tokenType;
+ private String secret;
+ private String issuer;
+ private String audience;
+ private Long expiration;
+
+}
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/SecurityConstants.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/SecurityConstants.java
new file mode 100644
index 0000000..12d3ef4
--- /dev/null
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/SecurityConstants.java
@@ -0,0 +1,19 @@
+package br.com.ifpb.pweb2.securitydemo.config;
+
+public class SecurityConstants {
+
+ public static final String AUTH_LOGIN_URL = "/api/authenticate";
+
+ // Signing key for HS512 algorithm
+ // Use http://www.allkeysgenerator.com/ para gerar uma chave
+ public static final String JWT_SECRET = "E07451F5-583D-4B1A-8AF1-A3AF70AABD43";
+
+ // JWT token defaults
+ public static final String TOKEN_HEADER = "Authorization";
+ public static final String TOKEN_PREFIX = "Bearer ";
+ public static final String TOKEN_TYPE = "JWT";
+ public static final String TOKEN_ISSUER = "secure-api";
+ public static final String TOKEN_AUDIENCE = "secure-app";
+
+ private SecurityConstants() {}
+}
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/WebSecurityConfig.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/WebSecurityConfig.java
index 43671e8..e5de4cf 100644
--- a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/WebSecurityConfig.java
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/WebSecurityConfig.java
@@ -1,28 +1,54 @@
package br.com.ifpb.pweb2.securitydemo.config;
+import br.com.ifpb.pweb2.securitydemo.config.jwt.JwtAuthenticationFilter;
+import br.com.ifpb.pweb2.securitydemo.config.jwt.JwtAuthorizationFilter;
+import br.com.ifpb.pweb2.securitydemo.service.UsuarioService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true, securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
- public WebSecurityConfig() {
+ private final SecurityConfig securityConfig;
+ private UsuarioService usuarioService;
+
+ @Autowired
+ private ApplicationConfig applicationConfig;
+ private final UserDetailsService userDetailsService;
+
+ private final PasswordEncoder passwordEncoder;
+
+
+ public WebSecurityConfig(SecurityConfig securityConfig, UsuarioService usuarioService, UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
+ this.securityConfig = securityConfig;
+ this.usuarioService = usuarioService;
+ this.userDetailsService = userDetailsService;
+ this.passwordEncoder = passwordEncoder;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
- http
+ http.cors().and()
.authorizeRequests()
- .antMatchers("/api/**").authenticated()
.antMatchers("/publico").permitAll()
- .antMatchers("/usuarios").hasRole("ADMIN")
- .and()
- .sessionManagement()
+ .anyRequest().authenticated()
+ .and()
+ .addFilter(new JwtAuthenticationFilter(authenticationManager(), securityConfig))
+ .addFilter(new JwtAuthorizationFilter(authenticationManager(), securityConfig)).
+ sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
@@ -30,4 +56,23 @@ protected void configure(HttpSecurity http) throws Exception {
.csrf().disable();
}
+ @Override
+ public void configure(AuthenticationManagerBuilder auth) throws Exception {
+ if(!usuarioService.isEmpty()){
+ auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
+ }else{
+ auth.inMemoryAuthentication()
+ .passwordEncoder(passwordEncoder)
+ .withUser(applicationConfig.getAutenticacaoPadrao().getLogin())
+ .password(passwordEncoder.encode(applicationConfig.getAutenticacaoPadrao().getSenha()))
+ .authorities("ROLE_"+applicationConfig.getAutenticacaoPadrao().getPapel());
+ } }
+
+ @Bean
+ public CorsConfigurationSource corsConfigurationSource() {
+ final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
+ return source;
+ }
+
}
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/jwt/JwtAuthenticationFilter.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/jwt/JwtAuthenticationFilter.java
new file mode 100644
index 0000000..e309925
--- /dev/null
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/jwt/JwtAuthenticationFilter.java
@@ -0,0 +1,68 @@
+package br.com.ifpb.pweb2.securitydemo.config.jwt;
+
+import br.com.ifpb.pweb2.securitydemo.config.SecurityConfig;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.Keys;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
+
+ private final AuthenticationManager authenticationManager;
+
+ private final SecurityConfig securityConfig;
+
+ public JwtAuthenticationFilter(AuthenticationManager authenticationManager, SecurityConfig securityConfig) {
+ this.authenticationManager = authenticationManager;
+ this.securityConfig = securityConfig;
+ setFilterProcessesUrl(this.securityConfig.getAuthLoginUrl());
+ }
+
+ @Override
+ public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
+ String username = request.getParameter("usuario");
+ String password = request.getParameter("senha");
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
+
+ return authenticationManager.authenticate(authenticationToken);
+ }
+
+ @Override
+ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
+ FilterChain filterChain, Authentication authentication) {
+ UserDetails user = ((UserDetails) authentication.getPrincipal());
+
+ List roles = user.getAuthorities()
+ .stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.toList());
+
+ String signingKey = securityConfig.getSecret();
+
+ String token = Jwts.builder()
+ .signWith(Keys.hmacShaKeyFor(signingKey.getBytes()), SignatureAlgorithm.HS512)
+ .setHeaderParam("type", securityConfig.getTokenType())
+ .setIssuer(securityConfig.getIssuer()) //emissor
+ .setAudience(securityConfig.getAudience()) //destinatario
+ .setSubject(user.getUsername())
+ .setExpiration(new Date(System.currentTimeMillis() + securityConfig.getExpiration()))
+ .claim("roles", roles)
+ .compact();
+
+ response.addHeader("Authorization", "Bearer " + token);
+ }
+
+}
\ No newline at end of file
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/jwt/JwtAuthorizationFilter.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/jwt/JwtAuthorizationFilter.java
new file mode 100644
index 0000000..71bf44a
--- /dev/null
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/config/jwt/JwtAuthorizationFilter.java
@@ -0,0 +1,90 @@
+package br.com.ifpb.pweb2.securitydemo.config.jwt;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+import br.com.ifpb.pweb2.securitydemo.config.SecurityConfig;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jws;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.MalformedJwtException;
+import io.jsonwebtoken.SignatureException;
+import io.jsonwebtoken.UnsupportedJwtException;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
+
+ private final SecurityConfig securityConfig;
+
+ public JwtAuthorizationFilter(AuthenticationManager authenticationManager, SecurityConfig securityConfig) {
+ super(authenticationManager);
+ this.securityConfig = securityConfig;
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+ FilterChain filterChain) throws IOException, ServletException {
+ UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
+ if (authentication == null) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ filterChain.doFilter(request, response);
+ }
+
+ private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
+ String token = request.getHeader("Authorization");
+ if (token != null && !token.isEmpty() && token.startsWith("Bearer")) {
+ try {
+ String signingKey = securityConfig.getSecret();
+
+ Jws parsedToken = Jwts.parser()
+ .setSigningKey(signingKey.getBytes())
+ .parseClaimsJws(token.replace("Bearer ", ""));
+
+ String username = parsedToken
+ .getBody()
+ .getSubject();
+
+ List authorities = ((List>) parsedToken.getBody()
+ .get("roles")).stream()
+ .map(authority -> new SimpleGrantedAuthority((String) authority))
+ .collect(Collectors.toList());
+
+ if (username != null && !username.isEmpty()){
+ return new UsernamePasswordAuthenticationToken(username, null, authorities);
+ }
+
+ } catch (ExpiredJwtException exception) {
+ log.warn("Request to parse expired JWT : {} failed : {}", token, exception.getMessage());
+ } catch (UnsupportedJwtException exception) {
+ log.warn("Request to parse unsupported JWT : {} failed : {}", token, exception.getMessage());
+ } catch (MalformedJwtException exception) {
+ log.warn("Request to parse invalid JWT : {} failed : {}", token, exception.getMessage());
+ } catch (SignatureException exception) {
+ log.warn("Request to parse JWT with invalid signature : {} failed : {}", token, exception.getMessage());
+ } catch (IllegalArgumentException exception) {
+ log.warn("Request to parse empty or null JWT : {} failed : {}", token, exception.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/PublicoController.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/PublicoController.java
index c056b1c..77e096c 100644
--- a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/PublicoController.java
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/PublicoController.java
@@ -10,7 +10,7 @@ public class PublicoController {
@GetMapping
public String exibirMensagem() {
- return "Olá, meu acesso é público";
+ return "Olá, meu acesso é públicooooo";
}
}
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/UsuarioController.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/UsuarioController.java
index b1d2d8c..3c3ddd3 100644
--- a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/UsuarioController.java
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/controller/UsuarioController.java
@@ -3,8 +3,10 @@
import br.com.ifpb.pweb2.securitydemo.domain.Usuario;
import br.com.ifpb.pweb2.securitydemo.service.UsuarioException;
import br.com.ifpb.pweb2.securitydemo.service.UsuarioService;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@@ -15,12 +17,14 @@
public class UsuarioController {
private final UsuarioService usuarioService;
+ private BCryptPasswordEncoder bCryptPasswordEncoder;
- public UsuarioController(UsuarioService usuarioService) {
+
+ public UsuarioController(UsuarioService usuarioService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.usuarioService = usuarioService;
+ this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
-
@GetMapping("/{login}")
public Usuario recuperarPorLogin(@PathVariable("login") String login) {
return usuarioService.recuperarPorLogin(login).orElseThrow(RuntimeException::new);
@@ -28,17 +32,28 @@ public Usuario recuperarPorLogin(@PathVariable("login") String login) {
@GetMapping
public List listarUsuarios() {
+
return usuarioService.listarUsuarios();
}
@PostMapping
public ResponseEntity salvarUsuario(@RequestBody @Valid Usuario usuario) {
try {
- usuario = usuarioService.salvarUsuario(usuario);
+ if (usuario == null){
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
+ }
+ usuario.setSenha(bCryptPasswordEncoder.encode(usuario.getPassword()));
+
+ if (usuarioService.salvarUsuario(usuario) == null){
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
+ }
+
+ return ResponseEntity.status(HttpStatus.CREATED).build();
+
+
} catch(UsuarioException e) {
return ResponseEntity.badRequest().header("erro", e.getMessage()).build();
}
- return ResponseEntity.ok(usuario);
}
@PutMapping
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/domain/Usuario.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/domain/Usuario.java
index ad72737..0b0e899 100644
--- a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/domain/Usuario.java
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/domain/Usuario.java
@@ -1,5 +1,6 @@
package br.com.ifpb.pweb2.securitydemo.domain;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.hibernate.validator.constraints.br.CPF;
import org.springframework.security.core.GrantedAuthority;
@@ -53,36 +54,43 @@ public class Usuario implements UserDetails {
private LocalDateTime dataCadastro;
@Override
+ @JsonIgnore
public Collection extends GrantedAuthority> getAuthorities() {
return Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
@Override
+ @JsonIgnore
public String getPassword() {
return senha;
}
@Override
+ @JsonIgnore
public String getUsername() {
return login;
}
+ @JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
+ @JsonIgnore
public boolean isAccountNonLocked() {
return true;
}
@Override
+ @JsonIgnore
public boolean isCredentialsNonExpired() {
return true;
}
@Override
+ @JsonIgnore
public boolean isEnabled() {
return true;
}
diff --git a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/service/UsuarioService.java b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/service/UsuarioService.java
index 08636e1..8d2a503 100644
--- a/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/service/UsuarioService.java
+++ b/exemplos/02-seguranca/src/main/java/br/com/ifpb/pweb2/securitydemo/service/UsuarioService.java
@@ -58,7 +58,13 @@ public Optional recuperarPorNomeEIdade(String nome, Integer idade) {
}
public Usuario atualizarUsuario(Usuario usuario) {
+ usuario.setSenha(passwordEncoder.encode(usuario.getSenha()));
return this.usuarioRepository.save(usuario);
}
+
+ public boolean isEmpty(){
+ return usuarioRepository.findAll().isEmpty();
+ }
+
}
diff --git a/exemplos/02-seguranca/src/main/resources/application-dev.yaml b/exemplos/02-seguranca/src/main/resources/application-dev.yaml
index 05c263f..821399f 100644
--- a/exemplos/02-seguranca/src/main/resources/application-dev.yaml
+++ b/exemplos/02-seguranca/src/main/resources/application-dev.yaml
@@ -1,8 +1,8 @@
spring:
datasource:
- url: jdbc:postgresql://localhost:5432/pweb2
+ url: jdbc:postgresql://localhost:5433/pweb2
username: postgres
- password: secret
+ password: 1327
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
diff --git a/exemplos/02-seguranca/src/main/resources/application.yaml b/exemplos/02-seguranca/src/main/resources/application.yaml
index c5af4b7..5882cd2 100644
--- a/exemplos/02-seguranca/src/main/resources/application.yaml
+++ b/exemplos/02-seguranca/src/main/resources/application.yaml
@@ -7,7 +7,16 @@ spring:
app:
autenticacaoPadrao:
- login: diego
- senha: 123
+ login: admin
+ senha: 1234
papel: ADMIN
- tipoAutenticacao: BANCO
\ No newline at end of file
+ tipoAutenticacao: BANCO
+
+security:
+ authLoginUrl: /login
+ tokenType: JWT
+ issuer: ifpb
+ audience: pweb2
+ expiration: 3600000
+ secret: s5v8y/A?D(G+KbPeShVmYq3t6w9z$C&E)H@McQfTjWnZr4u7x!A%D*G-JaNdRgUk
+ ## Use: https://www.allkeysgenerator.com/ para gerar o segredo
\ No newline at end of file
diff --git a/run.sh b/run.sh
new file mode 100644
index 0000000..93055b9
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,2 @@
+sudo docker run -p 5433:5432 -d --name postgres --env POSTGRES_PASSWORD=1327 postgres:9.4.19
+sudo docker start postgres