Pular para o conteúdo principal

Quiz: Spring Security

Teste seus conhecimentos sobre segurança Spring, JWT e OAuth2.

30 questões - Clique em cada pergunta para revelar a resposta.


Questões 1-10: Fundamentos de Security​

Questão 1: Qual dependência adicionar para Spring Security?

Resposta:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Por padrão, todas as rotas são protegidas.


Questão 2: O que acontece ao adicionar Spring Security sem configuração?

Resposta:

  • Todas as rotas exigem autenticação
  • Um formulário de login é exibido
  • Um usuário user é criado com uma senha gerada (exibida nos logs)
  • CSRF está ativado

Questão 3: Como configurar a segurança no Spring Boot 3?

Resposta:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());

return http.build();
}
}

Questão 4: Qual a diferença entre authenticated() e permitAll()?

Resposta:

  • permitAll(): acessível sem autenticação
  • authenticated(): requer um usuário autenticado
  • hasRole("X"): requer o papel X
  • hasAuthority("X"): requer a autoridade X

Questão 5: Como definir usuários em memória?

Resposta:

@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("password"))
.roles("USER")
.build();

UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin"))
.roles("ADMIN")
.build();

return new InMemoryUserDetailsManager(user, admin);
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Questão 6: Como implementar UserDetailsService com banco de dados?

Resposta:

@Service
public class CustomUserDetailsService implements UserDetailsService {

private final UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));

return org.springframework.security.core.userdetails.User.builder()
.username(user.getEmail())
.password(user.getPassword())
.roles(user.getRole().name())
.build();
}
}

Questão 7: Por que codificar as senhas?

Resposta:

  • Segurança: senhas ilegíveis se o banco for comprometido
  • BCrypt: gera um hash diferente a cada vez (sal integrado)
  • Obrigatório: Spring Security recusa senhas em texto puro
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Questão 8: Qual a diferença entre Role e Authority?

Resposta:

  • Role: prefixado automaticamente por ROLE_
  • Authority: usado como está
// Ambos são equivalentes:
.hasRole("ADMIN") // verifica ROLE_ADMIN
.hasAuthority("ROLE_ADMIN")

// Autoridades personalizadas
.hasAuthority("READ_USERS")
.hasAuthority("WRITE_USERS")

Questão 9: O que é CSRF e quando desativar?

Resposta: CSRF (Cross-Site Request Forgery) protege contra requisições maliciosas.

Desative para APIs REST stateless (JWT):

http.csrf(csrf -> csrf.disable())

Mantenha ativado para aplicações com sessões.


Questão 10: Como recuperar o usuário logado?

Resposta:

// Em um controller
@GetMapping("/me")
public User getCurrentUser(@AuthenticationPrincipal UserDetails userDetails) {
return userService.findByEmail(userDetails.getUsername());
}

// Ou via SecurityContextHolder
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();

Questões 11-20: JWT​

Questão 11: O que é um JWT?

Resposta: JSON Web Token - um token composto por 3 partes:

  1. Header: algoritmo e tipo
  2. Payload: claims (dados)
  3. Signature: verificação de integridade

Formato: header.payload.signature (codificado em Base64)


Questão 12: Quais são os claims padrão de um JWT?

Resposta:

ClaimDescrição
subSujeito (usuário)
issEmissor
expExpiração
iatEmitido em
nbfNão antes de
jtiJWT ID (único)

Questão 13: Como gerar um JWT?

Resposta:

@Service
public class JwtService {

@Value("${jwt.secret}")
private String secret;

public String generateToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}

private Key getSigningKey() {
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
}
}

Questão 14: Como validar um JWT?

Resposta:

public boolean isTokenValid(String token, UserDetails userDetails) {
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();

String username = claims.getSubject();
Date expiration = claims.getExpiration();

return username.equals(userDetails.getUsername())
&& !expiration.before(new Date());
} catch (JwtException e) {
return false;
}
}

Questão 15: Como implementar um filtro JWT?

Resposta:

@Component
public class JwtAuthFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {

String header = request.getHeader("Authorization");

if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
String username = jwtService.extractUsername(token);

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails user = userDetailsService.loadUserByUsername(username);

if (jwtService.isTokenValid(token, user)) {
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}

chain.doFilter(request, response);
}
}

Questão 16: Como configurar o filtro JWT?

Resposta:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();
}

Questão 17: O que é um Refresh Token?

Resposta: Um token de longa duração para obter novos access tokens sem novo login:

  • Access Token: curta duração (15min-1h)
  • Refresh Token: longa duração (7-30 dias)
// Endpoint de refresh
@PostMapping("/refresh")
public TokenResponse refresh(@RequestBody RefreshRequest request) {
String refreshToken = request.getRefreshToken();
// Validar e gerar novo access token
}

Questão 18: Como armazenar o segredo JWT de forma segura?

Resposta:

  1. Variáveis de ambiente
  2. Vault (HashiCorp Vault)
  3. AWS Secrets Manager
  4. Spring Cloud Config (criptografado)
# NUNCA faça commit do segredo!
jwt:
secret: ${JWT_SECRET}

Questão 19: Como invalidar um JWT?

Resposta: Os JWTs são stateless, portanto não podem ser revogados diretamente. Soluções:

  1. Blacklist: armazenar tokens revogados (Redis)
  2. Expiração curta: tokens válidos por pouco tempo
  3. Versão do usuário: invalidar a cada troca de senha

Questão 20: Como proteger endpoints com anotações?

Resposta:

@EnableMethodSecurity
@Configuration
public class SecurityConfig { }

@RestController
public class UserController {

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/users")
public List<User> getAllUsers() { }

@PreAuthorize("#id == authentication.principal.id or hasRole('ADMIN')")
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) { }
}

Questões 21-30: OAuth2 e Segurança Avançada​

Questão 21: O que é OAuth2?

Resposta: Protocolo de autorização que permite a uma aplicação acessar recursos de um usuário via um provedor terceiro (Google, GitHub, etc.) sem compartilhar a senha.


Questão 22: Quais são os papéis no OAuth2?

Resposta:

  • Resource Owner: o usuário
  • Client: a aplicação
  • Authorization Server: Google, GitHub...
  • Resource Server: API protegida

Questão 23: Como configurar OAuth2 com Google?

Resposta:

spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope: openid, profile, email
http.oauth2Login(Customizer.withDefaults());

Questão 24: Como personalizar o sucesso do login OAuth2?

Resposta:

http.oauth2Login(oauth -> oauth
.successHandler((request, response, authentication) -> {
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
userService.processOAuthUser(oauthUser);
response.sendRedirect("/dashboard");
})
);

Questão 25: O que é CORS?

Resposta: Cross-Origin Resource Sharing - permite requisições de outros domínios:

@Configuration
public class CorsConfig {

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:3000"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(List.of("*"));
config.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}

Questão 26: Como adicionar headers de segurança?

Resposta:

http.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives("default-src 'self'"))
.frameOptions(frame -> frame.deny())
.xssProtection(xss -> xss.enable())
);

Questão 27: Como limitar tentativas de login?

Resposta: Implemente um rate limiter:

@Component
public class LoginAttemptService {

private final LoadingCache<String, Integer> attemptsCache;

public void loginFailed(String ip) {
int attempts = attemptsCache.get(ip);
attemptsCache.put(ip, attempts + 1);
}

public boolean isBlocked(String ip) {
return attemptsCache.get(ip) >= MAX_ATTEMPTS;
}
}

Questão 28: Como auditar acessos seguros?

Resposta:

@Component
public class SecurityAuditListener {

@EventListener
public void onAuthSuccess(AuthenticationSuccessEvent event) {
log.info("Login bem-sucedido: {}", event.getAuthentication().getName());
}

@EventListener
public void onAuthFailure(AuthenticationFailureBadCredentialsEvent event) {
log.warn("Falha no login: {}", event.getAuthentication().getName());
}
}

Questão 29: Como testar a segurança?

Resposta:

@WebMvcTest(UserController.class)
@Import(SecurityConfig.class)
class UserControllerSecurityTest {

@Test
@WithMockUser(roles = "ADMIN")
void adminCanAccessAdminEndpoint() {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isOk());
}

@Test
@WithMockUser(roles = "USER")
void userCannotAccessAdminEndpoint() {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isForbidden());
}
}

Questão 30: Quais são as boas práticas de segurança no Spring?

Resposta:

  1. Sempre codifique as senhas (BCrypt)
  2. Use HTTPS em produção
  3. Configure CORS de forma restrita
  4. Implemente rate limiting
  5. Valide todas as entradas
  6. Faça log dos eventos de segurança
  7. Use segredos fortes e externalize-os
  8. Atualize as dependências regularmente

Pontuação​

PontuaçãoNível
27-30Excelente - Segurança dominada
21-26Bom - Algumas revisões
15-20Médio - Releia os capítulos
Menos de 15Precisa revisar

Voltar ao Módulo 8