Boa noite, Seguindo as mudanças na versão 3.1 apresentadas no curso, percebi que ocorre um erro de validação quando se usa "roles" para usuários diferentes. Testei a exclusão com usuários com roles "ROLE_ADMIN" e "ROLE_USER", contudo os dois conseguiram realizar a exclusão. Existem alguma forma de tratar para que não ocorra.
@Table(name = "users")
@Entity(name = "Usuario")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Usuario implements UserDetails{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String login;
private String password;
private boolean enabled;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// return List.of(new SimpleGrantedAuthority("ROLE_USER");
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (Role role : getRoles()) {
authorities.add(new SimpleGrantedAuthority(role.getName().trim()));
}
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return login;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
}
==========
public interface UsuarioRepository extends JpaRepository <Usuario, Long> {
@Query("SELECT u FROM Usuario u JOIN FETCH u.roles where u.login = :login ")
Usuario findByUserNameFetchRoles(@Param("login") String login);
}
======
@Configuration
@EnableWebSecurity
public class SecurityConfigurations {
private static final String SIGN_UP_URL = "/login";
@Autowired
private SecurityFilter securityFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.csrf(csrf -> csrf.disable())
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(req -> {
// Não cheque essas requisições
req.requestMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll();
req.requestMatchers(HttpMethod.DELETE, "/medicos").hasAuthority("ROLE_ADMIN");
req.requestMatchers(HttpMethod.DELETE, "/pacientes").hasAuthority("ROLE_ADMIN");
// Qualquer outra requisição deve ser checada
req.anyRequest().authenticated();
})
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
======
@Component
public class SecurityFilter extends OncePerRequestFilter {
private static final String TOKEN_PREFIX = "Bearer ";
private static final String HEADER_STRING = "Authorization";
@Autowired
private TokenService tokenService;
@Autowired
private UsuarioRepository usuarioRepository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
var tokenJWT = recuperarToken(request);
if(tokenJWT != null){
var subject = tokenService.getSubject(tokenJWT);
var usuario = usuarioRepository.findByUserNameFetchRoles(subject);
var authentication = new UsernamePasswordAuthenticationToken(usuario, null, usuario.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
private String recuperarToken(HttpServletRequest request) {
var authorizationHeader = request.getHeader(HEADER_STRING);
if(authorizationHeader != null){
return authorizationHeader.replace(TOKEN_PREFIX, "").trim();
}
return null;
}
}