Saudação, amigos! Amanhã iniciarão as primeiras aulas no novo segmento do curso
"Developer on Spring Framework" . A esse respeito, tradicionalmente compartilhamos material útil sobre o assunto.

Neste artigo, exploraremos o uso do OAuth2 e JWT em conjunto com o Spring Boot e o Spring Security.
Servidor de Autorização
Um servidor de autorização é o componente mais importante na arquitetura de segurança da API da Web. O servidor de autorização atua como um único ponto de autorização e permite que seus aplicativos e pontos de extremidade HTTP definam as funções do seu aplicativo.
Servidor de Recursos
O servidor de autorização fornece aos clientes um token de acesso para acessar os pontos de extremidade HTTP do servidor de recursos. Um servidor de recursos é uma coleção de bibliotecas que contém pontos de extremidade HTTP, recursos estáticos e páginas da web dinâmicas.
OAuth2
OAuth2 é um protocolo de autorização que permite que um cliente (terceiros) acesse os recursos do seu aplicativo. Para criar um aplicativo OAuth2, precisamos conhecer o tipo de concessão (código de autorização), o ID do cliente e o segredo do cliente.
Token JWT
Um token JWT é um token JSON da Web. É usado para representar informações seguras de identificação (reivindicações) entre duas partes. Você pode encontrar mais informações sobre os tokens JWT em
www.jwt.io.Vamos criar um aplicativo OAuth2 usando tokens JWT, que incluirá um servidor de autorização e um servidor de recursos.
Primeiro, precisamos adicionar as dependências ao nosso arquivo de construção.
Os usuários do Maven podem adicionar as seguintes dependências ao
pom.xml
.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</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>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </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>
Nota do tradutor - para java anterior a 9, você também deve adicionar as seguintes dependências: <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.2.11</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.2.11</version> </dependency>
Os usuários do Gradle podem incluir as seguintes dependências no arquivo
build.gradle
.
compile('org.springframework.boot:spring-boot-starter-security') compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('org.springframework.security:spring-security-test') compile("org.springframework.security.oauth:spring-security-oauth2") compile('org.springframework.security:spring-security-jwt') compile("org.springframework.boot:spring-boot-starter-jdbc") compile("com.h2database:h2:1.4.191")
onde
- Spring Boot Starter Security - implementa o Spring Security
- Spring Security OAuth2 - implementa estruturas OAUTH2 para a operação do servidor de autorização e do servidor de recursos.
- Spring Security JWT - gera toques JWT
- Spring Boot Starter JDBC - acesso ao banco de dados para verificação do usuário.
- Spring Boot Starter Web - Fornece pontos de extremidade HTTP.
- Banco de dados H2 - armazena informações do usuário para autenticação e autorização.
O arquivo
pom.xml
completo
pom.xml
mostrado abaixo.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tutorialspoint</groupId> <artifactId>websecurityapp</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>websecurityapp</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</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>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </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>
Gradle — build.gradle
buildscript { ext { springBootVersion = '1.5.9.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' group = 'com.tutorialspoint' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter-security') compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('org.springframework.security:spring-security-test') compile("org.springframework.security.oauth:spring-security-oauth2") compile('org.springframework.security:spring-security-jwt') compile("org.springframework.boot:spring-boot-starter-jdbc") compile("com.h2database:h2:1.4.191") }
Agora, inclua as anotações
@EnableResourceServer
e
@EnableResourceServer
no arquivo principal do aplicativo Spring Boot para que o aplicativo funcione como servidor de autorização e servidor de recursos.
Adicione também um ponto de extremidade HTTP simples (/ produtos) para acessar a API protegida pelo Spring Security usando um token JWT.
package com.tutorialspoint.websecurityapp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @EnableAuthorizationServer @EnableResourceServer @RestController public class WebsecurityappApplication { public static void main(String[] args) { SpringApplication.run(WebsecurityappApplication.class, args); } @RequestMapping(value = "/products") public String getProductName() { return "Honey"; } }
Defina uma classe POJO para armazenar informações de autenticação do usuário.
package com.tutorialspoint.websecurityapp; import java.util.ArrayList; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; public class UserEntity { private String username; private String password; private Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>(); public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Collection<GrantedAuthority> getGrantedAuthoritiesList() { return grantedAuthoritiesList; } public void setGrantedAuthoritiesList(Collection<GrantedAuthority> grantedAuthoritiesList) { this.grantedAuthoritiesList = grantedAuthoritiesList; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
Em seguida, para autenticação, adicione a classe CustomUser, que estende
org.springframework.security.core.userdetails.User
.
package com.tutorialspoint.websecurityapp; import org.springframework.security.core.userdetails.User; public class CustomUser extends User { private static final long serialVersionUID = 1L; public CustomUser(UserEntity user) { super(user.getUsername(), user.getPassword(), user.getGrantedAuthoritiesList()); } }
Crie uma
@Repository-
para recuperar informações do usuário do banco de dados e adicione os privilégios ROLE_SYSTEMADMIN. Essa classe também será usada no
CustomDetailsService
.
package com.tutorialspoint.websecurityapp; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Repository; @Repository public class OAuthDao { @Autowired private JdbcTemplate jdbcTemplate; public UserEntity getUserDetails(String username) { Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>(); String userSQLQuery = "SELECT * FROM USERS WHERE USERNAME=?"; List<UserEntity> list = jdbcTemplate.query(userSQLQuery, new String[] { username }, (ResultSet rs, int rowNum) -> { UserEntity user = new UserEntity(); user.setUsername(username); user.setPassword(rs.getString("PASSWORD")); return user; }); if (list.size() > 0) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_SYSTEMADMIN"); grantedAuthoritiesList.add(grantedAuthority); list.get(0).setGrantedAuthoritiesList(grantedAuthoritiesList); return list.get(0); } return null; } }
Para chamar o repositório DAO, você pode criar seu
UserDetailsService
, herdando de
org.springframework.security.core.userdetails.UserDetailsService
, conforme mostrado abaixo.
package com.tutorialspoint.websecurityapp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service public class CustomDetailsService implements UserDetailsService { @Autowired OAuthDao oauthDao; @Override public CustomUser loadUserByUsername(final String username) throws UsernameNotFoundException { UserEntity userEntity = null; try { userEntity = oauthDao.getUserDetails(username); CustomUser customUser = new CustomUser(userEntity); return customUser; } catch (Exception e) { e.printStackTrace(); throw new UsernameNotFoundException("User " + username + " was not found in the database"); } } }
Em seguida, crie uma
@onfiguration-
para habilitar o
Web Security
. Defina os parâmetros de criptografia de senha (
BCryptPasswordEncoder
) e o bean
AuthenticationManager
.
Esta classe
SecurityConfiguration
deve herdar da classe
WebSecurityConfigurerAdapter
.
package com.tutorialspoint.websecurityapp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; 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.builders.WebSecurity; 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.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private CustomDetailsService customDetailsService; @Bean public PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } @Override @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customDetailsService).passwordEncoder(encoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated().and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
Agora adicione uma classe para configurar o OAuth2. Nele, defina o ID do cliente, o Segredo do cliente, o JwtAccessTokenConverter, as chaves públicas e privadas para assinar e verificar o token e configure o
ClientDetailsServiceConfigurer
para escopos de token válidos.
package com.tutorialspoint.websecurityapp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; @Configuration public class OAuth2Config extends AuthorizationServerConfigurerAdapter { private String clientid = "tutorialspoint"; private String clientSecret = "my-secret-key"; private String privateKey = "private key"; private String publicKey = "public key"; @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Bean public JwtAccessTokenConverter tokenEnhancer() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey(privateKey); converter.setVerifierKey(publicKey); return converter; } @Bean public JwtTokenStore tokenStore() { return new JwtTokenStore(tokenEnhancer()); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore()) .accessTokenConverter(tokenEnhancer()); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient(clientid).secret(clientSecret).scopes("read", "write") .authorizedGrantTypes("password", "refresh_token").accessTokenValiditySeconds(20000) .refreshTokenValiditySeconds(20000); } }
Agora crie as chaves públicas e privadas usando o
openssl
.
Para gerar uma chave privada, você pode usar os seguintes comandos -
openssl genrsa -out jwt.pem 2048 openssl rsa -in jwt.pem
Para chave pública -
openssl rsa -in jwt.pem -pubout
Para o Spring Boot anterior à versão 1.5, adicione a seguinte propriedade ao arquivo
application.properties
(para determinar a ordem de filtragem dos recursos do OAuth2).
security.oauth2.resource.filter-order=3
Se você estiver usando um arquivo YAML, adicione o seguinte.
security: oauth2: resource: filter-order: 3
Agora crie os
data.sql
e
data.sql
no
classpath
no
src/main/resources/directory
para conectar o aplicativo ao banco de dados H2.
O arquivo
schema.sql
fica assim:
CREATE TABLE USERS (ID INT PRIMARY KEY, USERNAME VARCHAR(45), PASSWORD VARCHAR(60)); data.sql: INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES ( 1, 'tutorialspoint@gmail.com','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG'); INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES ( 2, 'myemail@gmail.com','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG');
Nota - A senha na tabela do banco de dados deve ser armazenada no formato Bcrypt Encoder.
Você pode criar um arquivo JAR executável e executar o aplicativo Spring Boot usando os seguintes comandos Maven ou Gradle.
Para o Maven, você pode usar o comando abaixo -
mvn clean install
Após o “BUILD SUCCESS”, você pode encontrar os arquivos JAR no diretório de
target
.
Para Gradle, você pode usar o comando -
gradle clean build
Após o “BUILD SUCCESSFUL”, você pode encontrar os arquivos JAR no diretório
build/libs
.
Agora execute o arquivo JAR com o comando -
java –jar <
JARFILE
>
O aplicativo lançado no Tomcat na porta 8080.

Agora envie uma solicitação POST via POSTMAN para receber um token OAUTH2.
http://localhost:8080/oauth/token
Agora adicione os cabeçalhos da solicitação -
- Autorização - Básico com seu ID do cliente e segredo do cliente.
- Tipo de conteúdo - application / x-www-form-urlencoded

E solicitar parâmetros -
- grant_type = senha
- nome de usuário = seu nome
- password = sua senha

Agora execute e obtenha
access_token
como mostrado.

Agora, crie uma solicitação para a API do servidor de recursos com um token Bearer no cabeçalho.

Obtemos o resultado como mostrado abaixo.

Aguardamos seus comentários e também informamos que, até 31 de maio, você poderá
participar do curso por um preço especial.