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çãoauthenticated(): requer um usuário autenticadohasRole("X"): requer o papel XhasAuthority("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:
- Header: algoritmo e tipo
- Payload: claims (dados)
- 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:
| Claim | Descrição |
|---|---|
sub | Sujeito (usuário) |
iss | Emissor |
exp | Expiração |
iat | Emitido em |
nbf | Não antes de |
jti | JWT 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:
- Variáveis de ambiente
- Vault (HashiCorp Vault)
- AWS Secrets Manager
- 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:
- Blacklist: armazenar tokens revogados (Redis)
- Expiração curta: tokens válidos por pouco tempo
- 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:
- Sempre codifique as senhas (BCrypt)
- Use HTTPS em produção
- Configure CORS de forma restrita
- Implemente rate limiting
- Valide todas as entradas
- Faça log dos eventos de segurança
- Use segredos fortes e externalize-os
- Atualize as dependências regularmente
Pontuação
| Pontuação | Nível |
|---|---|
| 27-30 | Excelente - Segurança dominada |
| 21-26 | Bom - Algumas revisões |
| 15-20 | Médio - Releia os capítulos |
| Menos de 15 | Precisa revisar |