Spring Boot Jwt Autenticacao

May 12, 2018 | Author: breno jeronimo | Category: Hypertext Transfer Protocol, Web Development, Computing, Technology, Software


Comments



Description

Autenticação com JWT no Spring Boot http://andreybleme.com/2017-04-01/autenticaca...ANDREYBLEME • Autenticação com JWT no Spring Boot 01 APR 2017 java spring security JSON Web Token (JWT), é um padrão que define uma forma segura de transmitir mensagens utilizando um token compacto e self-contained no formato de um objeto JSON. É compacto porque além de leve, pode ser enviado através de um HTTP header, via URL, ou como parâmetro no corpo de uma requisição HTTP. Dizemos que um JWT é self-contained porque seu payload possui toda informação necessária para autenticar um usuário, assim, não é necessário fazer mais que uma única consulta na base de dados. JSON Web Tokens são comumente utilizados quando precisamos de autenticação em aplicações com arquiteturas stateless (REST por exemplo). JWTs nos permitem autenticar um usuário e garantir que as demais requisições serão feitas de forma autenticada, sendo possível restringir acessos a recursos e serviços com diferentes níveis de permissões. Estrutura do JSON Web Token Um JWT é composto por três partes separadas por ponto. hhh.ppp.sss • H eader • P ayload • S ignature O header consiste em duas partes diferentes: o tipo do token (no caso JWT), e o nome do algorítimo responsável pelo hashing, HMAC SHA256 ou RSA. 1 { 2 "alg": "HS256", 3 "typ": "JWT" 4 } header.json hosted with ❤ by GitHub view raw Esse JSON será encoded via Base64Url e irá compor a primeira parte do token. O payload contém o que chamamos de claims. Claims são atributos da entidade (no caso usuário) e metadados. Um exemplo de payload: 1 { 2 "sub": "1337", 3 "name": "Lucas Bleme", 4 "admin": true 5 } payload.json hosted with ❤ by GitHub view raw Essse JSON será encoded via Base64Url e irá compor a segunda parte do token. A signature verifica que o remetente do JWT é quem diz ser para garantir que a mensagem não foi alterada durante o tráfego. Para criar a assinatura (signature), utiliza-se o header Base64 encoded, o payload também Base64 encoded, e o algorítimo especificado no header. Utilizando o algorítimo HMAC SHA256, a signature ficaria assim: 1 HMACSHA256( 2 base64UrlEncode(header) + "." + 3 base64UrlEncode(payload), 4 secret) signature.js hosted with ❤ by GitHub view raw Por fim teremos uma String em Base64 separada por pontos, compondo o JSON Web Token. eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTQ5MTUyMjg2NH0.OZQPWEgs-JaABOCEodulSiN-yd-T1gmZzrswY4kaNKNI_FyOVFJPaBsAqkcD3SgN010Y4VSFSNh6DXNq 1 of 9 11/4/17, 2:37 PM vamos mapear a URL /users retornando um JSON simples quando ela for acessada.annotation. 1 package com. Agora vamos extender um pouco mais.java hosted with ❤ by GitHub view raw Como fizemos na nossa classe principal. precisamos criar um RestController . vamos adicionar o endpoint na única classe que temos no projeto. 2 3 import org. 16 } 17 18 @RequestMapping("/home") 19 public String hello() { 20 return "Hello buddy!".annotation.bind.bind. Fazendo isso.RestController. você pode usar o JWT Debugger e ver o token sendo formado na prática. criando a classe UserController . os dados serão retornados para o client em formato JSON.bind.springframework.spring. um novo projeto pronto para ser executado será criado já com todas as dependências que precisamos para executar a aplicação. "country":"Brazil"}.\"country\":\"China\"}]}". 1 {"users":[{"name":"Lucas".annotation.web. 6 7 @RestController 8 public class UserController { 9 10 @RequestMapping("/users") 11 @ResponseBody 12 public String getUsers() { 13 return "{\"users\":[{\"name\":\"Lucas\".boot.RequestMapping. Quando queremos criar métodos que representem endpoints no Spring.{"name":"Jackie".web. adicionar apenas “Web”. Com essa anotação.web.annotation.springframework. 7 import org.io/ e no campo “dependencies”.bind. Essa classe também será anotada com @RestController . args).boot.springframework. Por essa razão adicionamos a anotação @ResponseBody . aqui também criamos um endpoint. 1 package com. quando uma requisição especificar em seu header que aceita application/json .class.jwtme. Criando o projeto Spring boot A ideia é implementar autenticação para uma aplicação Springboot. 21 } 22 } JwtmeApplication.EnableAutoConfiguration.springframework. 15 } 16 } UserController.RequestMapping.springframework."country":"China"}]} return.SpringApplication. mais tarde criaremos outras rotas. \"country\":\"Brazil\"}. 4 import org.RestController.controllers.bind.autoconfigure. Feito isso.json hosted with ❤ by GitHub view raw 2 of 9 11/4/17." + 14 "{\"name\":\"Jackie\". Para testar esses conceitos e montar um JWT. Por hora.com/2017-04-01/autenticaca.run(JwtmeApplication.java hosted with ❤ by GitHub view raw Executando o método main. 2:37 PM ..boot. acessando o endereço localhost:8080/home devemos ver a mensagem ““Hello buddy!”.springframework.springframework.ResponseBody.jwtme. criaremos uma rota /home para verificarmos o funcionamento correto da nossa aplicação. a classe principal. 4 import org.web.springframework. A diferença é que nosso método retorna um JSON. 6 import org. Para criar um novo projeto spring boot basta acessar https://start. 5 import org.autoconfigure.annotation. 5 import org. 2 3 import org..SpringBootApplication.Autenticação com JWT no Spring Boot http://andreybleme. 8 9 @SpringBootApplication 10 @RestController 11 @EnableAutoConfiguration 12 public class JwtmeApplication { 13 14 public static void main(String[] args) { 15 SpringApplication.web. authentication.class). vamos cria-la em um novo pacote com. 1 package com. 9 import org.addFilterBefore(new JWTLoginFilter("/login".authorizeRequests() 18 .config.EnableWebSecurity. Nesse exemplo.http.security. a primeira coisa que queremos fazer é deixar de expor os recursos de /users publicamente.authentication.web.builders.Configuration.springframework..config..HttpMethod. 2:37 PM .security. vamos expor publicamente apenas os recursos disponíveis em /home e /login .jsonwebtoken</groupId> 20 <artifactId>jjwt</artifactId> 21 <version>0. Para acessar /users será necessário que o usuário envie ao nosso servidor um token JWT válido.permitAll() 20 .csrf().springframework. vamos adicionar duas dependências ao pom.security.springframework. vamos adicionar segurança à nossa aplicação com JSON Web Tokens! Nesse exemplo.security .web. Qualquer pessoa pode acessar a lista de usuários do nosso servidor. 29 UsernamePasswordAuthenticationFilter. Essa nova classe vai ser uma classe filha da classe WebSecurityConfigurerAdapter do Spring security. 10 11 @Configuration 12 @EnableWebSecurity 13 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 14 15 @Override 16 protected void configure(HttpSecurity httpSecurity) throws Exception { 17 httpSecurity. Para que esse recurso seja restrito apenas a usuários autenticados.security.boot</groupId> 15 <artifactId>spring-boot-starter-security</artifactId> 16 </dependency> 17 18 <dependency> 19 <groupId>io.context.annotation.class) 26 27 // filtra outras requisições para verificar a presença do JWT no header 28 .builders. e a segunda. 2 3 import org.xml hosted with ❤ by GitHub view raw Adicionadas as dependências. Para isso.springframework.jwtme.UsernamePasswordAuthenticationFilter. 30 } 31 32 @Override 33 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 34 // cria uma conta default 3 of 9 11/4/17.anyRequest().jwtme. A primeira é spring-boot-starter-security que nos permite trabalhar com autenticação no Spring.boot</groupId> 9 <artifactId>spring-boot-starter-test</artifactId> 10 <scope>test</scope> 11 </dependency> 12 13 <dependency> 14 <groupId>org.web.annotation.POST.configuration.xml . vamos criar uma configuração que restrinja esse acesso criando uma nova classe chamada WebSecurityConfig .config. 5 import org.com/2017-04-01/autenticaca.authenticated() 21 .springframework. 25 UsernamePasswordAuthenticationFilter. 8 import org. 6 import org. os recursos da nossa aplicação estão expostos para todos.Autenticação com JWT no Spring Boot http://andreybleme.permitAll() 19 .and() 22 23 // filtra requisições de login 24 .disable().security.configuration.springframework.springframework.springframework. authenticationManager()).0</version> 22 </dependency> 23 </dependencies> pom. é jjwt que vai gerenciar nossos JWTs.annotation.config.antMatchers("/home").boot</groupId> 4 <artifactId>spring-boot-starter-web</artifactId> 5 </dependency> 6 7 <dependency> 8 <groupId>org.7. Adicionando segurança às rotas Até esse momento.springframework.web.annotation.addFilterBefore(new JWTAuthenticationFilter(). "/login").antMatchers(HttpMethod. 1 <dependencies> 2 <dependency> 3 <groupId>org. 4 import org. Por tanto.annotation.HttpSecurity. 7 import org.springframework.security.WebSecurityConfigurerAdapter.AuthenticationManagerBuilder. springframework.xml de configuração! Tudo foi feito pragmaticamente com uma classe de configuração anotada com @Configuration . Criando os JWT Services no Spring boot Nossos JWT services serão responsáveis por gerara e validar nossos JWT tokens. Não se preocupe com erros de compilação.withUser("admin") 37 . SECRET) 28 .getHeader(HEADER_STRING). 4 import java. 13 import io. "")) 41 . 22 23 static void addAuthentication(HttpServletResponse response.SignatureAlgorithm.util. 29 30 response.jwtme. Repare que também adicionamos uma conta default aqui.getBody() 4 of 9 11/4/17. Por tanto.http.jsonwebtoken. 2 3 import java. Vamos cria-las em breve. para decidir como essas requisições deverão ser tratadas. As classes JWTLoginFilter e JWTAuthenticationFilter serão responsáveis por lidar com login e validação da autenticação dos usuários quando acessarem outras rotas. String username) { 24 String JWT = Jwts. Para criar e verificar nossos tokens.addHeader(HEADER_STRING. 35 36 if (token != null) { 37 // faz parse do token 38 String user = Jwts.com/2017-04-01/autenticaca. 31 } 32 33 static Authentication getAuthentication(HttpServletRequest request) { 34 String token = request. Nesse exemplo vamos criar um token baseado em username e um expiration_time . vamos criar a classe TokenAuthenticationService dentro do mesmo pacote com. e que o endpoint /login está disponível apenas via requisições do tipo POST.. 11 12 import io. Elas serão as classes responsáveis por filtrar as requisições feitas em /login e em todas as outras rotas.. 10 import org. para testarmos o funcionamento da autenticação. Nela vamos utilizar a classe que incluímos como dependência io. Para todas as demais rotas a autenticação é necessária.builder() 25 .inMemoryAuthentication() 36 .Jwts para validar os tokens. 8 9 import org.Collections. Uma grande vantagem de estarmos utilizando o Spring boot aqui.Autenticação com JWT no Spring Boot http://andreybleme. 19 static final String SECRET = "MySecret". 21 static final String HEADER_STRING = "Authorization". nem adicionar arquivos . é que em momento algum foi necessário mudar o código já existente das rotas. 35 auth.parser() 39 .HttpServletResponse.http.jsonwebtoken.Date.signWith(SignatureAlgorithm. em seguida iremos assiná-lo com uma palavra chave secret . 20 static final String TOKEN_PREFIX = "Bearer". antes nos preocuparmos com elas.security. já que ainda não criamos as classes JWTLoginFilter e JWTAuthenticationFilter . 7 import javax.roles("ADMIN").HttpServletRequest.HS512. 5 6 import javax.jwtme.compact().util.parseClaimsJws(token. 39 } 40 } WebSecurityConfig.UsernamePasswordAuthenticationToken. TOKEN_PREFIX + " " + JWT).setSigningKey(SECRET) 40 .Authentication.setSubject(username) 26 . 2:37 PM . 1 package com.servlet. 14 15 public class TokenAuthenticationService { 16 17 // EXPIRATION_TIME = 10 dias 18 static final long EXPIRATION_TIME = 860_000_000.java hosted with ❤ by GitHub view raw Nessa classe definimos que todos podem acessar /home . vamos ter que criar as classes que irão lidar com os JWTs.core.security.currentTimeMillis() + EXPIRATION_TIME)) 27 .Jwts.password("password") 38 .springframework.security .replace(TOKEN_PREFIX.authentication.setExpiration(new Date(System.jsonwebtoken.servlet.security. io.web.springframework. 19 20 public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter { 21 22 protected JWTLoginFilter(String url.springframework.matcher.getPassword().security. 14 import org.HttpServletRequest.addAuthentication(response.util.security.authenticate( 35 new UsernamePasswordAuthenticationToken( 36 credentials.jackson. 46 } 47 } 48 return null. ServletException { 30 31 AccountCredentials credentials = new ObjectMapper() 32 .IOException..HttpServletResponse.servlet.ServletException. e utilizamos o AuthenticationManager para verificar se os dados são correspondentes aos dados do nosso usuário existente. Caso os dados estejam 5 of 9 11/4/17.springframework.java hosted with ❤ by GitHub view raw Autenticando os JWTs Já temos tudo que precisamos para usar os JWTs no processo de autenticação. null. ServletException { 49 50 TokenAuthenticationService. Pegamos o username e password da requisição.Authentication. AccountCredentials.emptyList()).servlet. 1 package com. 13 import org. Agora vamos criar a classe JWTLoginFilter para interceptar as requisições do tipo POST feitas em /login e tentar autenticar o usuário.springframework. 9 import javax.security. 41 } 42 43 @Override 44 protected void successfulAuthentication( 45 HttpServletRequest request.getUsername().ObjectMapper.authentication.servlet. 47 FilterChain filterChain. 4 import java.. 24 setAuthenticationManager(authManager).FilterChain. um método irá retornar um JWT com a autorização Authorization no cabeçalho da resposta. HttpServletResponse response) 29 throws AuthenticationException.springframework.class).http.AuthenticationManager. 37 credentials. 49 } 50 51 } TokenAuthenticationService. 25 } 26 27 @Override 28 public Authentication attemptAuthentication(HttpServletRequest request.core. 17 18 import com. Collections.getSubject(). IOException.com/2017-04-01/autenticaca. 7 import javax.http.web. 42 .getName()).security.security.core.jwtme.java hosted with ❤ by GitHub view raw Aqui o método attemptAuthentication é quem lida com a tentativa de autenticação.AbstractAuthenticationProcessingFilter. AuthenticationManager authManager) { 23 super(new AntPathRequestMatcher(url)).Collections. auth.springframework. 2:37 PM . Quando o usuário for autenticado com sucesso. 15 import org.getInputStream(). 46 HttpServletResponse response.AntPathRequestMatcher.Autenticação com JWT no Spring Boot http://andreybleme. 8 import javax. 10 11 import org.security.emptyList() 39 ) 40 ).security. 48 Authentication auth) throws IOException. 38 Collections.databind.fasterxml.authentication.readValue(request. 43 44 if (user != null) { 45 return new UsernamePasswordAuthenticationToken(user. 12 import org.servlet.UsernamePasswordAuthenticationToken. 16 import org.AuthenticationException. 2 3 import java.util. 5 6 import javax. 33 34 return getAuthenticationManager().authentication. 51 } 52 53 } JWTLoginFilter. servlet.getAuthentication((HttpServletRequest) request).security.web. 23 24 SecurityContextHolder. 14 15 public class JWTAuthenticationFilter extends GenericFilterBean { 16 17 @Override 18 public void doFilter(ServletRequest request.springframework.java hosted with ❤ by GitHub view raw Nessa classe validamos a existência de um JWT nas requisições.ServletException.servlet.http. 26 } 27 28 } JWTAuthenticationFilter. 14 } 15 16 public String getPassword() { 17 return password.. Se tudo estiver funcionando corretamente. 1 package com.security. 1 package com. 4 5 import javax.io.password = password. com ajuda do service TokenAuthenticationService .context.core.setAuthentication(authentication). Agora sim.servlet. 9 import javax. 10 } 11 12 public void setUsername(String username) { 13 this. a resposta deve ser Access Denied . 2:37 PM .. 6 private String password. 12 import org. 7 8 public String getUsername() { 9 return username. vamos enviar uma requisição do tipo POST para o 6 of 9 11/4/17.core.jwtme.springframework. 6 import javax. 10 11 import org.getContext(). Requests de login portanto. 7 import javax. ServletException { 20 21 Authentication authentication = TokenAuthenticationService 22 . 2 3 import java. que será utilizada para enviarmos as credenciais da conta a ser validada quando fizermos requisições do tipo POST à URL /login .doFilter(request. FilterChain filterChain) 19 throws IOException.java hosted with ❤ by GitHub view raw Executando a autenticação Nossa aplicação agora está segura e podemos realizar autenticações com JWT! Após reiniciar a aplicação vamos tentar acessar o endereço http://localhost:8080/users .com/2017-04-01/autenticaca. corretos.username = username. 2 3 public class AccountCredentials { 4 5 private String username. ServletResponse response. response). 22 } 23 } AccountCredentials.ServletResponse. devem ser feitas com um objeto do tipo AccountCredentials em seu body. 18 } 19 20 public void setPassword(String password) { 21 this. criaremos a classe JWTAuthenticationFilter . invocamos o método successfulAuthentication para enviar ao service TokenAuthenticationService o username do usuário para que este service adicione um JWT à nossa resposta (response).springframework.Authentication. Agora só falta criarmos a classe AccountCredentials . 8 import javax.FilterChain.ServletRequest.GenericFilterBean.HttpServletRequest. 13 import org.servlet.security.security.jwtme. 25 filterChain. Para nos autenticarmos corretamente.IOException.filter.servlet.Autenticação com JWT no Spring Boot http://andreybleme.SecurityContextHolder. com/2017-04-01/autenticaca. 2:37 PM . endereço http://localhost:8080/login com as credencias do nosso usuário default no body.Autenticação com JWT no Spring Boot http://andreybleme. Para buscar os usuários. Usando o Postman a requisição feita com sucesso deve se parecer com isso: No header da resposta dessa requisição temos nosso token com o prefixo Bearer .. Referências e links úteis JSON Web Tokens REST Security with JWT What’s the difference between “Request Payload” vs “Form Data” Spring Initializr 7 of 9 11/4/17.. agora precisamos enviar no header da requisição nosso token incluindo o cabeçalho Authorization com o JWT que recebemos quando realizamos a autenticação com sucesso. △ ▽ • Responder • Compartilhar › Henrique Schmitt > Lucas Andrey • 2 meses atrás Sim.apache. Isso porquê valores estáticos são inicializados quando uma classe é criada. veja se este link te ajuda (https://cursos. "message": "No content to map due to end-of-input\n at [Source: org. 20 Comentários andreybleme  1 Entrar Ordenar por Mais votados  Recomendar ⤤ Compartilhar Participe da discussão.JsonMappingException". um token JWT só é válido enquanto a aplicação não é reiniciada! Esse pode ser o problema.. "status": 500. "status": 500..com/2017-04-01/autenticaca.get('Authorization').SignatureException". Agora é tentar encapsular em um jar e reutilizar em outros projetos. porém não tenho noção de como obter o token com Vue.jdbcAuthentication()..catalina. e se eu quiser validar usuário e senha indo até um repositório utilizando Spring Data? Vou dar autowired no repositório dentro de JWTLoginFilter ? △ ▽ • Responder • Compartilhar › Lucas Andrey Mod > Henrique Schmitt • 2 meses atrás Oi @Henrique Schmitt.. "path": "/rest/users" } △ ▽ • Responder • Compartilhar › Lucas Andrey Mod > Luis Henrique Borges • 2 meses atrás @Luis Henrique Borges o método "static void addAuthentication()" gera um novo TOKEN cada vez que a aplicação é iniciada. "exception": "io. gere um token. funcionou 100%. será que poderiam me ajudar? { "timestamp": 1504558932845. "error": "Internal Server Error".databind.. 2:37 PM . o retorno da minha requisição é exatamente igual o do post. "path": "/login" } sabe me dizer por que? △ ▽ • Responder • Compartilhar › 8 of 9 11/4/17. Dessa forma. Pode ser algum problema no servidor? △ ▽ • Responder • Compartilhar › Henrique > Henrique • 3 dias atrás Aliás. Configurei o Spring para trabalhar com o CORS. 1△ ▽ • Responder • Compartilhar › Henrique Schmitt • 2 meses atrás Ótimo tutorial.Autenticação com JWT no Spring Boot http://andreybleme. JWT validity cannot be asserted and should not be trusted. △ ▽ • Responder • Compartilhar › Luis Henrique Borges • 2 meses atrás Olá Estou com esse pequeno problema na hora de fazer a requisição..br.connector. column: 0]".jsonwebtoken.. Minha dúvida é. FAZER LOGIN COM OU REGISTRE-SE NO DISQUS ? Nome Sidronio Lima • 2 meses atrás Perfeito.usersByUsernameQuery(usersQuery) .. Faça o seguinte: Inicie a aplicação.headers. fiz com JdbcAuthentication.. na verdade a alteração deve ser feita na classe "WebSecurityConfig".'' recebo undefined.fasterxml. funcionou muito bem incluisve com autenticação JDBC.". muito bom teu post.. line: 1.dataSource(dataSource) . 1△ ▽ • Responder • Compartilhar › Douglas Pac Martins • 2 meses atrás Amigo estou recebendo via POSTMAN a seguinte resposta { "timestamp": 1503513455713. "error": "Internal Server Error". "exception": "com.passwordEncoder(bCryptPasswordEncoder).com. 1△ ▽ • Responder • Compartilhar › Henrique • 3 dias atrás Opa. obrigado! auth. "message": "JWT signature does not match locally computed signature.alura.jackson. Se ainda assim o problema persistir. Quando eu pego ''response.CoyoteInputStream@605aca6d. tente utilizá-lo na requisição sem reiniciar o server.authoritiesByUsernameQuery(rolesQuery) . No método "configure" vc não vai precisar criar uma conta default. com/2017-04-01/autenticaca.      © 2017 Lucas Andrey... All rights reserved. 2:37 PM . 9 of 9 11/4/17.Autenticação com JWT no Spring Boot http://andreybleme.
Copyright © 2024 DOKUMEN.SITE Inc.