├── .gitignore ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── redspark │ │ ├── SpringSecurityJwtApplication.java │ │ ├── controller │ │ └── MeController.java │ │ └── security │ │ ├── JWTAuthenticationFailureHandler.java │ │ ├── JWTAuthenticationSuccessHandler.java │ │ ├── StatelessAuthenticationFilter.java │ │ ├── TokenAuthenticationService.java │ │ ├── TokenHandler.java │ │ ├── UserAuthentication.java │ │ ├── WebSecurityConfig.java │ │ └── WebSecurityConfiguration.java └── resources │ └── application.properties └── test └── java └── io └── redspark └── SpringSecurityJwtApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/** 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | io.redspark 7 | SpringSecurityJWT 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | SpringSecurityJWT 12 | Exemplo Spring Security + JWT 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.3.0.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | 1.8 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-security 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-web 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-test 39 | test 40 | 41 | 42 | 43 | io.jsonwebtoken 44 | jjwt 45 | 0.6.0 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/SpringSecurityJwtApplication.java: -------------------------------------------------------------------------------- 1 | package io.redspark; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringSecurityJwtApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringSecurityJwtApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/controller/MeController.java: -------------------------------------------------------------------------------- 1 | package io.redspark.controller; 2 | 3 | import org.springframework.security.access.annotation.Secured; 4 | import org.springframework.security.core.Authentication; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | public class MeController { 10 | 11 | @Secured("ROLE_USUARIO") 12 | @RequestMapping("/security") 13 | public String security(Authentication authentication){ 14 | return "Acessando serviço seguro"; 15 | } 16 | 17 | @RequestMapping("/open") 18 | public String open(Authentication authentication){ 19 | return "Acessando serviço não seguro"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/JWTAuthenticationFailureHandler.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.security.core.AuthenticationException; 12 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 13 | 14 | public class JWTAuthenticationFailureHandler implements AuthenticationFailureHandler{ 15 | 16 | @Override 17 | public void onAuthenticationFailure(HttpServletRequest request, 18 | HttpServletResponse response, AuthenticationException exception) 19 | throws IOException, ServletException { 20 | 21 | this.updateHeaders(response); 22 | 23 | response.getWriter().print(exception.getMessage()); 24 | response.getWriter().flush(); 25 | } 26 | 27 | private void updateHeaders(HttpServletResponse response) { 28 | response.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE); 29 | response.setStatus(HttpStatus.FORBIDDEN.value()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/JWTAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 11 | 12 | public class JWTAuthenticationSuccessHandler implements AuthenticationSuccessHandler{ 13 | 14 | private TokenAuthenticationService tokenService; 15 | 16 | @Override 17 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 18 | tokenService.addAuthentication(response, authentication); 19 | } 20 | 21 | public JWTAuthenticationSuccessHandler(TokenAuthenticationService tokenService) { 22 | super(); 23 | this.tokenService = tokenService; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/StatelessAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package io.redspark.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 StatelessAuthenticationFilter extends GenericFilterBean { 16 | 17 | final TokenAuthenticationService authenticationService; 18 | 19 | public StatelessAuthenticationFilter(TokenAuthenticationService authenticationService) { 20 | this.authenticationService = authenticationService; 21 | } 22 | 23 | @Override 24 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 25 | throws IOException, ServletException { 26 | HttpServletRequest httpRequest = (HttpServletRequest) request; 27 | Authentication authentication = authenticationService.getAuthentication(httpRequest); 28 | SecurityContextHolder.getContext().setAuthentication(authentication); 29 | filterChain.doFilter(request, response); 30 | SecurityContextHolder.getContext().setAuthentication(null); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/TokenAuthenticationService.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.userdetails.User; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | 10 | public class TokenAuthenticationService { 11 | 12 | private static final String AUTH_HEADER_NAME = "X-AUTH-TOKEN"; 13 | 14 | private final TokenHandler tokenHandler; 15 | 16 | public TokenAuthenticationService(String secret, UserDetailsService userService) { 17 | tokenHandler = new TokenHandler(secret, userService); 18 | } 19 | 20 | public void addAuthentication(HttpServletResponse response, Authentication authentication) { 21 | final User user = (User) authentication.getPrincipal(); 22 | response.addHeader(AUTH_HEADER_NAME, tokenHandler.createTokenForUser(user)); 23 | } 24 | 25 | public Authentication getAuthentication(HttpServletRequest request) { 26 | final String token = request.getHeader(AUTH_HEADER_NAME); 27 | if (token != null) { 28 | final User user = tokenHandler.parseUserFromToken(token); 29 | if (user != null) { 30 | return new UserAuthentication(user); 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/TokenHandler.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import org.springframework.security.core.userdetails.User; 4 | import org.springframework.security.core.userdetails.UserDetailsService; 5 | 6 | import io.jsonwebtoken.Jwts; 7 | import io.jsonwebtoken.SignatureAlgorithm; 8 | 9 | public class TokenHandler { 10 | 11 | private final String secret; 12 | private final UserDetailsService userService; 13 | 14 | public TokenHandler(String secret, UserDetailsService userService) { 15 | this.secret = secret; 16 | this.userService = userService; 17 | } 18 | 19 | public User parseUserFromToken(String token) { 20 | String username = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject(); 21 | return (User) userService.loadUserByUsername(username); 22 | } 23 | 24 | public String createTokenForUser(User user) { 25 | return Jwts.builder().setSubject(user.getUsername()).signWith(SignatureAlgorithm.HS256, secret).compact(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/UserAuthentication.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import java.util.Collection; 4 | 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.userdetails.User; 8 | 9 | public class UserAuthentication implements Authentication{ 10 | 11 | private static final long serialVersionUID = 1L; 12 | private final User user; 13 | private boolean authentication = true; 14 | 15 | public UserAuthentication(User user) { 16 | super(); 17 | this.user = user; 18 | } 19 | 20 | @Override 21 | public String getName() { 22 | return user.getUsername(); 23 | } 24 | 25 | @Override 26 | public Collection getAuthorities() { 27 | return user.getAuthorities(); 28 | } 29 | 30 | @Override 31 | public Object getCredentials() { 32 | return user.getPassword(); 33 | } 34 | 35 | @Override 36 | public Object getDetails() { 37 | return user; 38 | } 39 | 40 | @Override 41 | public Object getPrincipal() { 42 | return user.getUsername(); 43 | } 44 | 45 | @Override 46 | public boolean isAuthenticated() { 47 | return authentication; 48 | } 49 | 50 | @Override 51 | public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { 52 | this.authentication = isAuthenticated; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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.core.userdetails.UserDetailsService; 10 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 11 | 12 | @Configuration 13 | @EnableWebSecurity 14 | @EnableGlobalMethodSecurity(securedEnabled = true) 15 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ 16 | 17 | @Autowired 18 | private UserDetailsService userDetailsService; 19 | 20 | public WebSecurityConfig() { 21 | super(true); 22 | } 23 | 24 | @Override 25 | protected void configure(HttpSecurity http) throws Exception { 26 | 27 | TokenAuthenticationService tokenAuthenticationService = new TokenAuthenticationService("REDSPARK_SECRET", userDetailsService); 28 | JWTAuthenticationSuccessHandler athenticationSuccessHandler = new JWTAuthenticationSuccessHandler(tokenAuthenticationService); 29 | JWTAuthenticationFailureHandler authenticationFailureHandler = new JWTAuthenticationFailureHandler(); 30 | 31 | http.formLogin().loginProcessingUrl("/login").successHandler(athenticationSuccessHandler).failureHandler(authenticationFailureHandler) 32 | .and().exceptionHandling().and().anonymous().and().authorizeRequests() 33 | .antMatchers("/login").permitAll().and() 34 | .addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/redspark/security/WebSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.redspark.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 6 | import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; 7 | import org.springframework.security.core.authority.AuthorityUtils; 8 | import org.springframework.security.core.userdetails.User; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | import org.springframework.security.core.userdetails.UserDetailsService; 11 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 | 13 | @Configuration 14 | public class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter { 15 | 16 | @Override 17 | public void init(AuthenticationManagerBuilder auth) throws Exception { 18 | auth.userDetailsService(userDetailsService()); 19 | } 20 | 21 | @Bean 22 | public UserDetailsService userDetailsService() { 23 | return new UserDetailsService() { 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return new User(username, username, true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USUARIO")); 28 | } 29 | 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caioferreira/SpringSecurityJWT/a741a4e85a78ee3d7678639e688d6d4cfe157713/src/main/resources/application.properties -------------------------------------------------------------------------------- /src/test/java/io/redspark/SpringSecurityJwtApplicationTests.java: -------------------------------------------------------------------------------- 1 | package io.redspark; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.web.WebAppConfiguration; 6 | import org.springframework.boot.test.SpringApplicationConfiguration; 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringApplicationConfiguration(classes = SpringSecurityJwtApplication.class) 11 | @WebAppConfiguration 12 | public class SpringSecurityJwtApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | --------------------------------------------------------------------------------