Problema com CORS e WebSocket no Angular
Olá, pessoal! Estou enfrentando um problema ao tentar fazer uma requisição de WebSocket no meu projeto Angular. A aplicação Angular está rodando no endereço http://localhost:4200/ e o servidor WebSocket está em http://localhost:8080/. Quando tento estabelecer a conexão, recebo o seguinte erro: Access to XMLHttpRequest at 'http://localhost:8080/ws/info?t=1741192064562' from origin 'http://localhost:4200/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Além disso, o seguinte erro é registrado: GET http://localhost:8080/ws/info?t=1741192064562 net::ERR_FAILED 404 (Not Found) Código que estou utilizando no backend (Spring Boot) WebSocketConfig.java (Configuração do WebSocket) @Configuration @EnableWebSocketMessageBroker @Order(Ordered.HIGHEST_PRECEDENCE + 99) @RequiredArgsConstructor public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { private final String allowedOrigin = "http://localhost:4200"; @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws") // Endpoint WebSocket .setAllowedOrigins(allowedOrigin) // Permite origens específicas .withSockJS(); // Permite fallback para SockJS } @Override public void addArgumentResolvers(List argumentResolvers) { argumentResolvers.add(new WebSocketAuthenticationPrincipalArgumentResolver()); } @Override public boolean configureMessageConverters(List messageConverters) { DefaultContentTypeResolver resolver = new DefaultContentTypeResolver(); resolver.setDefaultMimeType(MediaType.APPLICATION_JSON); MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); converter.setObjectMapper(new ObjectMapper()); converter.setContentTypeResolver(resolver); messageConverters.add(converter); return false; } } SecurityConfig.java (Configuração de segurança com CORS) @Configuration @EnableWebSecurity public class SecurityConfig { @SuppressWarnings("unused") @Autowired private CustomUserDetailsService userDetailsService; @Autowired SecurityFilter securityFilter; @SuppressWarnings("removal") @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(authorize -> authorize .requestMatchers(HttpMethod.POST, "/auth/login").permitAll() .requestMatchers(HttpMethod.POST, "/auth/register").permitAll() .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // Permite requisições OPTIONS .requestMatchers("/ws/**").permitAll() // Permite WebSocket .anyRequest().authenticated() ) .addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class) .cors().and(); return http.build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } } CorsConfig.java (Configuração do CORS) @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:4200") // Apenas Angular pode acessar .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // Métodos permitidos .allowedHeaders("*") // Permite qualquer cabeçalho .allowCredentials(true); // Permite envio de cookies/tokens } } Código no frontend (Angular) WebSocketService.ts (Serviço WebSocket) import { Injectable } from '@angular/core'; import SockJS from 'sockjs-client'; import { Client, over } from '@stomp/stompjs'; @Injectable({ providedIn: 'root', }) export class WebSocketService { private stompClient!: Client; private socketUrl = 'http://localhost:8080/ws'; // URL do WebSocket backend disconnect(): void { if (this.stompClient && this.stompClient.connected) { this.stompClient.disconnect(() => { console.log('Desconectado do WebSocket'); }); } } // Conectar ao WebSocket connect(callback: (message: any) => void): void { const socket = new SockJS(this.socketUrl);

Olá, pessoal! Estou enfrentando um problema ao tentar fazer uma requisição de WebSocket no meu projeto Angular. A aplicação Angular está rodando no endereço http://localhost:4200/ e o servidor WebSocket está em http://localhost:8080/. Quando tento estabelecer a conexão, recebo o seguinte
erro:
Access to XMLHttpRequest at 'http://localhost:8080/ws/info?t=1741192064562' from origin 'http://localhost:4200/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Além disso, o seguinte erro é registrado:
GET http://localhost:8080/ws/info?t=1741192064562 net::ERR_FAILED 404 (Not Found)
Código que estou utilizando no backend (Spring Boot)
WebSocketConfig.java (Configuração do WebSocket)
@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
private final String allowedOrigin = "http://localhost:4200";
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws") // Endpoint WebSocket
.setAllowedOrigins(allowedOrigin) // Permite origens específicas
.withSockJS(); // Permite fallback para SockJS
}
@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(new WebSocketAuthenticationPrincipalArgumentResolver());
}
@Override
public boolean configureMessageConverters(List messageConverters) {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(MediaType.APPLICATION_JSON);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(new ObjectMapper());
converter.setContentTypeResolver(resolver);
messageConverters.add(converter);
return false;
}
}
SecurityConfig.java (Configuração de segurança com CORS)
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@SuppressWarnings("unused")
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
SecurityFilter securityFilter;
@SuppressWarnings("removal")
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(HttpMethod.POST, "/auth/login").permitAll()
.requestMatchers(HttpMethod.POST, "/auth/register").permitAll()
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // Permite requisições OPTIONS
.requestMatchers("/ws/**").permitAll() // Permite WebSocket
.anyRequest().authenticated()
)
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
.cors().and();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
CorsConfig.java (Configuração do CORS)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:4200") // Apenas Angular pode acessar
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // Métodos permitidos
.allowedHeaders("*") // Permite qualquer cabeçalho
.allowCredentials(true); // Permite envio de cookies/tokens
}
}
Código no frontend (Angular)
WebSocketService.ts (Serviço WebSocket)
import { Injectable } from '@angular/core';
import SockJS from 'sockjs-client';
import { Client, over } from '@stomp/stompjs';
@Injectable({
providedIn: 'root',
})
export class WebSocketService {
private stompClient!: Client;
private socketUrl = 'http://localhost:8080/ws'; // URL do WebSocket backend
disconnect(): void {
if (this.stompClient && this.stompClient.connected) {
this.stompClient.disconnect(() => {
console.log('Desconectado do WebSocket');
});
}
}
// Conectar ao WebSocket
connect(callback: (message: any) => void): void {
const socket = new SockJS(this.socketUrl);
this.stompClient = over(socket);
this.stompClient.connect({'Authorization:' : 'Bearer ' + localStorage.getItem('auth-token')}, () => {
console.log('Conectado ao WebSocket');
// Assina o tópico de atualizações
this.stompClient.subscribe('/topic/updates', (message) => {
callback(JSON.parse(message.body)); // Processa a mensagem recebida
});
});
}
sendMessage(content: string): void {
if (this.stompClient && this.stompClient.connected) {
const chatMessage = { content };
this.stompClient.send('/app/message', {}, JSON.stringify(chatMessage));
}
}
}
WebSocketComponent.ts (Componente Angular para interação com o WebSocket)
import { Component, OnDestroy, OnInit } from '@angular/core';
import { WebSocketService } from '../../core/service/web-socket.service';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-web-socket',
imports: [CommonModule],
templateUrl: './web-socket.component.html',
styleUrl: './web-socket.component.css'
})
export class WebsocketComponent implements OnInit, OnDestroy {
messages: string[] = [];
constructor(private webSocketService: WebSocketService) {}
ngOnInit(): void {
this.webSocketService.connect((message: string) => {
this.messages.push(message);
});
}
sendMessage(): void {
this.webSocketService.sendMessage('Olá, WebSocket!');
}
ngOnDestroy(): void {
this.webSocketService.disconnect();
}
}