├── .gitignore ├── pom.xml └── src ├── main ├── java │ └── br │ │ └── com │ │ └── treinaweb │ │ └── springbootapi │ │ ├── DemoApplication.java │ │ ├── config │ │ └── SwaggerConfig.java │ │ ├── controller │ │ └── PessoaController.java │ │ ├── entity │ │ ├── Pessoa.java │ │ └── Usuario.java │ │ ├── repository │ │ └── PessoaRepository.java │ │ └── security │ │ ├── JWTAuthenticationFilter.java │ │ ├── JWTLoginFilter.java │ │ ├── TokenAuthenticationService.java │ │ └── WebSecurityConfig.java └── resources │ └── application.properties └── test └── java └── br └── com └── treinaweb └── springbootapi └── DemoApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | .mvn/ 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | mvnw 33 | mvnw.cmd 34 | 35 | ## MAC OS X 36 | **/.DS_Store -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.1.6.RELEASE 9 | 10 | 11 | br.com.treinaweb 12 | springbootapi 13 | 0.0.1-SNAPSHOT 14 | demo 15 | Demo project for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-data-jpa 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-security 33 | 34 | 35 | 36 | mysql 37 | mysql-connector-java 38 | runtime 39 | 40 | 41 | io.springfox 42 | springfox-swagger2 43 | 2.9.2 44 | 45 | 46 | io.springfox 47 | springfox-swagger-ui 48 | 2.9.2 49 | 50 | 51 | io.jsonwebtoken 52 | jjwt 53 | 0.9.1 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-test 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-maven-plugin 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.config; 2 | 3 | import java.util.List; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.HttpHeaders; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | 12 | import io.swagger.models.auth.In; 13 | import springfox.documentation.builders.ApiInfoBuilder; 14 | import springfox.documentation.builders.PathSelectors; 15 | import springfox.documentation.builders.RequestHandlerSelectors; 16 | import springfox.documentation.builders.ResponseMessageBuilder; 17 | import springfox.documentation.schema.ModelRef; 18 | import springfox.documentation.service.ApiInfo; 19 | import springfox.documentation.service.ApiKey; 20 | import springfox.documentation.service.AuthorizationScope; 21 | import springfox.documentation.service.Contact; 22 | import springfox.documentation.service.ResponseMessage; 23 | import springfox.documentation.service.SecurityReference; 24 | import springfox.documentation.spi.DocumentationType; 25 | import springfox.documentation.spi.service.contexts.SecurityContext; 26 | import springfox.documentation.spring.web.plugins.Docket; 27 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 28 | 29 | @Configuration 30 | @EnableSwagger2 31 | public class SwaggerConfig { 32 | @Bean 33 | public Docket api() { 34 | return new Docket(DocumentationType.SWAGGER_2) 35 | .select() 36 | .apis(RequestHandlerSelectors.basePackage("br.com.treinaweb.springbootapi.controller")) 37 | .paths(PathSelectors.any()) 38 | .build() 39 | .useDefaultResponseMessages(false) 40 | .globalResponseMessage(RequestMethod.GET, responseMessageForGET()) 41 | .securitySchemes(Arrays.asList(new ApiKey("Token Access", HttpHeaders.AUTHORIZATION, In.HEADER.name()))) 42 | .securityContexts(Arrays.asList(securityContext())) 43 | .apiInfo(apiInfo()); 44 | } 45 | 46 | private ApiInfo apiInfo() { 47 | return new ApiInfoBuilder() 48 | .title("Simple Spring Boot REST API") 49 | .description("\"Um exemplo de aplicação Spring Boot REST API\"") 50 | .version("1.0.0") 51 | .license("Apache License Version 2.0") 52 | .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"") 53 | .contact(new Contact("Wladimilson", "https://treinaweb.com.br", "contato@treinaweb.com.br")) 54 | .build(); 55 | } 56 | 57 | private List responseMessageForGET() 58 | { 59 | return new ArrayList() { 60 | private static final long serialVersionUID = 1L; 61 | 62 | { 63 | add(new ResponseMessageBuilder() 64 | .code(500) 65 | .message("500 message") 66 | .responseModel(new ModelRef("Error")) 67 | .build()); 68 | add(new ResponseMessageBuilder() 69 | .code(403) 70 | .message("Forbidden!") 71 | .build()); 72 | }}; 73 | } 74 | 75 | private SecurityContext securityContext() { 76 | return SecurityContext.builder() 77 | .securityReferences(defaultAuth()) 78 | .forPaths(PathSelectors.ant("/pessoa/**")) 79 | .build(); 80 | } 81 | 82 | List defaultAuth() { 83 | AuthorizationScope authorizationScope 84 | = new AuthorizationScope("ADMIN", "accessEverything"); 85 | AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; 86 | authorizationScopes[0] = authorizationScope; 87 | return Arrays.asList( 88 | new SecurityReference("Token Access", authorizationScopes)); 89 | } 90 | 91 | //http://localhost:8080/swagger-ui.html 92 | //.apis(RequestHandlerSelectors.basePackage("br.com.ciceroednilson")) 93 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/controller/PessoaController.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.controller; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import javax.validation.Valid; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.PathVariable; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import io.swagger.annotations.ApiOperation; 18 | import io.swagger.annotations.ApiResponse; 19 | import io.swagger.annotations.ApiResponses; 20 | 21 | import br.com.treinaweb.springbootapi.entity.Pessoa; 22 | import br.com.treinaweb.springbootapi.repository.PessoaRepository; 23 | 24 | @RestController 25 | public class PessoaController { 26 | 27 | @Autowired 28 | private PessoaRepository _pessoaRepository; 29 | 30 | @ApiOperation(value = "Retorna uma lista de pessoas") 31 | @ApiResponses(value = { 32 | @ApiResponse(code = 200, message = "Retorna a lista de pessoa"), 33 | @ApiResponse(code = 403, message = "Você não tem permissão para acessar este recurso"), 34 | @ApiResponse(code = 500, message = "Foi gerada uma exceção"), 35 | }) 36 | @RequestMapping(value = "/pessoa", method = RequestMethod.GET, produces="application/json") 37 | public List Get() { 38 | return _pessoaRepository.findAll(); 39 | } 40 | 41 | @RequestMapping(value = "/pessoa/{id}", method = RequestMethod.GET, produces="application/json") 42 | public ResponseEntity GetById(@PathVariable(value = "id") long id) 43 | { 44 | Optional pessoa = _pessoaRepository.findById(id); 45 | if(pessoa.isPresent()) 46 | return new ResponseEntity(pessoa.get(), HttpStatus.OK); 47 | else 48 | return new ResponseEntity<>(HttpStatus.NOT_FOUND); 49 | } 50 | 51 | @RequestMapping(value = "/pessoa", method = RequestMethod.POST, produces="application/json", consumes="application/json") 52 | public Pessoa Post(@Valid @RequestBody Pessoa pessoa) 53 | { 54 | return _pessoaRepository.save(pessoa); 55 | } 56 | 57 | @RequestMapping(value = "/pessoa/{id}", method = RequestMethod.PUT, produces="application/json", consumes="application/json") 58 | public ResponseEntity Put(@PathVariable(value = "id") long id, @Valid @RequestBody Pessoa newPessoa) 59 | { 60 | Optional oldPessoa = _pessoaRepository.findById(id); 61 | if(oldPessoa.isPresent()){ 62 | Pessoa pessoa = oldPessoa.get(); 63 | pessoa.setNome(newPessoa.getNome()); 64 | _pessoaRepository.save(pessoa); 65 | return new ResponseEntity(pessoa, HttpStatus.OK); 66 | } 67 | else 68 | return new ResponseEntity<>(HttpStatus.NOT_FOUND); 69 | } 70 | 71 | @RequestMapping(value = "/pessoa/{id}", method = RequestMethod.DELETE, produces="application/json") 72 | public ResponseEntity Delete(@PathVariable(value = "id") long id) 73 | { 74 | Optional pessoa = _pessoaRepository.findById(id); 75 | if(pessoa.isPresent()){ 76 | _pessoaRepository.delete(pessoa.get()); 77 | return new ResponseEntity<>(HttpStatus.OK); 78 | } 79 | else 80 | return new ResponseEntity<>(HttpStatus.NOT_FOUND); 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/entity/Pessoa.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.entity; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | 9 | import io.swagger.annotations.ApiModelProperty; 10 | 11 | @Entity 12 | public class Pessoa 13 | { 14 | @ApiModelProperty(value = "Código da pessoa") 15 | @Id 16 | @GeneratedValue(strategy = GenerationType.AUTO) 17 | private long id; 18 | 19 | @ApiModelProperty(value = "Nome da pessoa") 20 | @Column(nullable = false) 21 | private String nome; 22 | 23 | public long getId() { 24 | return id; 25 | } 26 | 27 | public String getNome() { 28 | return nome; 29 | } 30 | 31 | public void setNome(String nome) { 32 | this.nome = nome; 33 | } 34 | 35 | public void setId(long id) { 36 | this.id = id; 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/entity/Usuario.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.entity; 2 | 3 | public class Usuario { 4 | 5 | private String username; 6 | private String password; 7 | 8 | public String getUsername() { 9 | return username; 10 | } 11 | 12 | public String getPassword() { 13 | return password; 14 | } 15 | 16 | public void setPassword(String password) { 17 | this.password = password; 18 | } 19 | 20 | public void setUsername(String username) { 21 | this.username = username; 22 | } 23 | 24 | @Override 25 | public String toString() 26 | { 27 | return username + " - " + password; 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/repository/PessoaRepository.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import br.com.treinaweb.springbootapi.entity.Pessoa; 7 | 8 | @Repository 9 | public interface PessoaRepository extends JpaRepository { } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/security/JWTAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.security; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.ServletRequest; 8 | import javax.servlet.ServletResponse; 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import org.springframework.security.core.Authentication; 12 | import org.springframework.security.core.context.SecurityContextHolder; 13 | import org.springframework.web.filter.GenericFilterBean; 14 | 15 | public class JWTAuthenticationFilter extends GenericFilterBean { 16 | 17 | @Override 18 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 19 | throws IOException, ServletException { 20 | 21 | Authentication authentication = TokenAuthenticationService 22 | .getAuthentication((HttpServletRequest) request); 23 | 24 | SecurityContextHolder.getContext().setAuthentication(authentication); 25 | filterChain.doFilter(request, response); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/security/JWTLoginFilter.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.security; 2 | 3 | import java.io.IOException; 4 | import java.util.Collections; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.Authentication; 14 | import org.springframework.security.core.AuthenticationException; 15 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 16 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 17 | 18 | import br.com.treinaweb.springbootapi.entity.Usuario; 19 | 20 | import com.fasterxml.jackson.databind.ObjectMapper; 21 | 22 | public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter { 23 | 24 | protected JWTLoginFilter(String url, AuthenticationManager authManager) { 25 | super(new AntPathRequestMatcher(url)); 26 | setAuthenticationManager(authManager); 27 | } 28 | 29 | @Override 30 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) 31 | throws AuthenticationException, IOException, ServletException { 32 | 33 | Usuario credentials = new ObjectMapper() 34 | .readValue(request.getInputStream(), Usuario.class); 35 | 36 | return getAuthenticationManager().authenticate( 37 | new UsernamePasswordAuthenticationToken( 38 | credentials.getUsername(), 39 | credentials.getPassword(), 40 | Collections.emptyList() 41 | ) 42 | ); 43 | } 44 | 45 | @Override 46 | protected void successfulAuthentication( 47 | HttpServletRequest request, 48 | HttpServletResponse response, 49 | FilterChain filterChain, 50 | Authentication auth) throws IOException, ServletException { 51 | 52 | TokenAuthenticationService.addAuthentication(response, auth.getName()); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/security/TokenAuthenticationService.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.security; 2 | 3 | import java.io.IOException; 4 | import java.util.Collections; 5 | import java.util.Date; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 11 | import org.springframework.security.core.Authentication; 12 | 13 | import io.jsonwebtoken.Jwts; 14 | import io.jsonwebtoken.SignatureAlgorithm; 15 | 16 | public class TokenAuthenticationService { 17 | 18 | // EXPIRATION_TIME = 10 dias 19 | static final long EXPIRATION_TIME = 860_000_000; 20 | static final String SECRET = "MySecret"; 21 | static final String TOKEN_PREFIX = "Bearer"; 22 | static final String HEADER_STRING = "Authorization"; 23 | 24 | static void addAuthentication(HttpServletResponse response, String username) { 25 | String JWT = Jwts.builder() 26 | .setSubject(username) 27 | .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) 28 | .signWith(SignatureAlgorithm.HS512, SECRET) 29 | .compact(); 30 | 31 | response.addHeader("Content-Type", "application/json"); 32 | 33 | try { 34 | response.getWriter().write(String.format("{ \"token\": \"%s\" }", JWT)); 35 | response.getWriter().flush(); 36 | response.getWriter().close(); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | static Authentication getAuthentication(HttpServletRequest request) { 43 | String token = request.getHeader(HEADER_STRING); 44 | 45 | if (token != null) { 46 | String user = Jwts.parser() 47 | .setSigningKey(SECRET) 48 | .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) 49 | .getBody() 50 | .getSubject(); 51 | 52 | if (user != null) { 53 | return new UsernamePasswordAuthenticationToken(user, null, Collections.emptyList()); 54 | } 55 | } 56 | return null; 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/main/java/br/com/treinaweb/springbootapi/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi.security; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.http.HttpMethod; 5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 10 | 11 | @Configuration 12 | @EnableWebSecurity 13 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 14 | 15 | @Override 16 | protected void configure(HttpSecurity httpSecurity) throws Exception { 17 | httpSecurity.csrf().disable().authorizeRequests() 18 | .antMatchers(HttpMethod.GET, "/").permitAll() 19 | .antMatchers(HttpMethod.GET, "/v2/api-docs").permitAll() 20 | .antMatchers(HttpMethod.GET, "/swagger-ui.html").permitAll() 21 | .antMatchers(HttpMethod.GET, "/webjars/**").permitAll() 22 | .antMatchers(HttpMethod.GET, "/swagger-resources/**").permitAll() 23 | .antMatchers(HttpMethod.POST, "/login").permitAll() 24 | .anyRequest().authenticated() 25 | .and() 26 | 27 | .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), 28 | UsernamePasswordAuthenticationFilter.class) 29 | 30 | .addFilterBefore(new JWTAuthenticationFilter(), 31 | UsernamePasswordAuthenticationFilter.class); 32 | } 33 | 34 | @Override 35 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 36 | auth.inMemoryAuthentication() 37 | .withUser("admin") 38 | .password("{noop}password") 39 | .roles("ADMIN"); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ## Database Properties 2 | spring.datasource.url = jdbc:mysql://localhost:3306/treinaweb?useSSL=false 3 | spring.datasource.username=root 4 | spring.datasource.password=1234 5 | ## Hibernate Properties 6 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect 7 | spring.jpa.hibernate.ddl-auto = update 8 | ## Spring Security 9 | jwt.secret=springbootapi-exemplo -------------------------------------------------------------------------------- /src/test/java/br/com/treinaweb/springbootapi/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package br.com.treinaweb.springbootapi; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------