Skip to content

Commit

Permalink
Fim Curso: Adicionando Segurança a uma
Browse files Browse the repository at this point in the history
API REST com Spring
Security
  • Loading branch information
ducrz committed May 25, 2022
1 parent 4e3f67d commit 6c86a3c
Show file tree
Hide file tree
Showing 31 changed files with 978 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Instrutor: Gleyson Sampaio

Adicionando Segurança a uma API REST com Spring Security

Apresentação e visão geral do curso

- Introdução sobre segurança
- Habilitando segurança com Spring
- Configure Adapter
- Autenticação com banco de dados
- JWT - JSON Web Token
- E muito mais...

Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
Springboot Security com JWT

Habilitando segurança com Spring

Introdução

Spring Security é apenas um grupo de filteos de servlet que ajudam você a adicionar autenticação e autorização ao seu aplicativo da web.


Terminologia

A autenticação refere-se ao processo de verificação da identidade de um usuário, com base nas credenciais fornecidas.
Um exemplo comum é inserir um nome de usuário e uma senha ao fazer login em um site.
Você pode pensar nisso como uma resposta à pergunta Quem é você?

Autorização refere-se ao processo de determinar se um usuário tem permissão adequada para executar uma ação específica ou ler dados específicos, supondo que o usuário seja autenticado com êxito.
Você pode pensar nisso como uma resposta à pergunta Um usuário pode fazer/ler isso?

Princípio refere-se ao usuário autenticado no momento

Autoridade concedida refere-se à permissão o usuário autenticado

Função refere-se a um grupo de permissões do usuário autenticado

Habilitando Segurança

Em um projeto Spring Boot Web você precisa somente incluir a dependência no pom.xml

Autenticação simples

O Spring possui algumas configurações para definir os usuários na sua camada de segurança.

Como sabemos por padrão o Spring Security habilita um usuário de nome user e gera uma senha aleatoriamente a cada inicialização. Para aplicações em produção esta não é uma abordagem um tanto aconselhável, e é por isso que vamos conhecer outras configurações de segurança.

No application.properties

O Spring Security verifica se existe alguma configuração de segurança no arquivo application.properties.

spring.security.user.name=user
spring.security.user.password=user123
spring.security.user.roles=USERS


Em Memória

Esta configuração permite criar mais de um usuário e perfis de acesso.

É necessário criar uma classe que estenda WebSecurityConfigureAdapter.

Existem algumas implementações de criptografias utilizadas pelo Spring Security

- use {bcrypt} for BcryptPasswordEncode (mais comum)
- use {noop} for NoOpPasswordEncoder
- use {pbkdf2} for Pbkf2PasswordEncoder
- Use {scrypt} for SCryptPasswordEncoder
- Use {sha256} for StandardPasswordEncoder


Configure Adapter

Nos exemplos acima já podemos considerar um nível de segurança em nossa aplicação, mas se percebermos o esforço de configuração para as novas funcionalidades poderá não ser uma abordagem tão satisfatória.
Para isso vamos tentar deixar a parte da configuração centralizada na nossa WebSecurityConfig, removendo configurações adicionais em nossos controllers.



Autenticação com Banco de dados

Auth Database

Interação com banco de dados.

O Spring Boot dispõe de uma facilidade para integrar aplicações com banco de dados com o Spring Data JPA.



JWT - JSON Web Token - Parte 1

O JSON Web Token - JWT é um padrão da internet para criação de dados com assinatura opcional /ou criptografia cujo conteúdo contém o JSON que afirma algum número de declarações. Os tokens são assinados usando um segredo privado ou uma chave pública/privada.


Qual a estrutura do JWT?

JWT é uma representação dividida em três partes:

- Header
- Payload
- Signature

Portanto, um JWT normalmente parece-se com o seguinte: xxxxx.yyyyy.zzzzz.

Header

O Header i cabeçalho normalmente consiste em duas partes: o tipo de token, que é JWT e o algoritmo de assinatura que está sendo utilizado, como o HMAC SHA256 ou RSA.

{
"alg": "HS256",
"typ": "JWT"
}

Payload

De fato a estrutura do corpo contendo as informações de autenticação e autorização de um usuário.

{
"sub": "glysns",
"name": "GLEYSON SAMPAIO",
"roles": ["USERS", "MANAGERS"]
}


Signature

Para criar a parte da assinatura, você deve pegar o cabeçalho codificado, o payload codificado, a chave secreta, o algoritmo especificado no cabeçalho e assiná-lo.

JWT - JSON Web Token - Parte 2


JWT - JSON Web Token - Parte 3


JWT - JSON Web Token - Parte 4


Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Conclusão e para saber mais
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Compiled class file
*.class

*.idea/
*.idea

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/.idea/compiler.xml
/.idea/encodings.xml
/.idea/oficial.iml
/mvnw.cmd
/mvnw
/.idea/modules.xml
/.idea/misc.xml
/.idea/vcs.xml
/.mvn/wrapper/MavenWrapperDownloader.java
target/
/target
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>dio</groupId>
<artifactId>dio-spring-security-jwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dio-spring-security-jwt</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dio.dio.spring.security.jwt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DioSpringSecurityJwtApplication {

public static void main(String[] args) {
SpringApplication.run(DioSpringSecurityJwtApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package dio.dio.spring.security.jwt.controller;

import dio.dio.spring.security.jwt.dtos.Login;
import dio.dio.spring.security.jwt.dtos.Sessao;
import dio.dio.spring.security.jwt.model.User;
import dio.dio.spring.security.jwt.repository.UserRepository;
import dio.dio.spring.security.jwt.security.JWTCreator;
import dio.dio.spring.security.jwt.security.JWTObject;
import dio.dio.spring.security.jwt.security.SecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
public class LoginController {
@Autowired
private PasswordEncoder encoder;
@Autowired
private SecurityConfig securityConfig;
@Autowired
private UserRepository repository;

@PostMapping("/login")
public Sessao logar(@RequestBody Login login){
User user = repository.findByUsername(login.getUsername());
if(user!=null) {
boolean passwordOk = encoder.matches(login.getPassword(), user.getPassword());
if (!passwordOk) {
throw new RuntimeException("Senha inválida para o login: " + login.getUsername());
}
//Estamos enviando um objeto Sessão para retornar mais informações do usuário
Sessao sessao = new Sessao();
sessao.setLogin(user.getUsername());

JWTObject jwtObject = new JWTObject();
jwtObject.setIssuedAt(new Date(System.currentTimeMillis()));
jwtObject.setExpiration((new Date(System.currentTimeMillis() + SecurityConfig.EXPIRATION)));
jwtObject.setRoles(user.getRoles());
sessao.setToken(JWTCreator.create(SecurityConfig.PREFIX, SecurityConfig.KEY, jwtObject));
return sessao;
}else {
throw new RuntimeException("Erro ao tentar fazer login");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dio.dio.spring.security.jwt.controller;

import dio.dio.spring.security.jwt.model.User;
import dio.dio.spring.security.jwt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService service;
@PostMapping
public void postUser(@RequestBody User user){
service.createUser(user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dio.dio.spring.security.jwt.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WelcomeController {
@GetMapping
public String welcome(){
return "Welcome to My Spring Boot Web API";
}
@GetMapping("/users")
public String users() {
return "Authorized user";
}
@GetMapping("/managers")
public String managers() {
return "Authorized manager";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dio.dio.spring.security.jwt.dtos;

public class Login {
private String username;
private String password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dio.dio.spring.security.jwt.dtos;

public class Sessao {
private String login;
private String token;

public String getLogin() {
return login;
}

public void setLogin(String login) {
this.login = login;
}

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}
}
Loading

0 comments on commit 6c86a3c

Please sign in to comment.