java - 连接到 WebSocket 时如何修复“Access-Control-Allow-Origin”错误?
问题描述
我正在开发 SockJS 和 WebSocket 类型的项目,对于前端我使用 React,在后端使用 Spring 的 WebSockets 实现。但是当我尝试连接到我的 WebSocket 时出现 CORS 错误。
Access to XMLHttpRequest at 'http://localhost:8080/ws/info?t=1579096675068' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
在 Java 项目中,我包含了这个 CORS 配置:
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration configuration = new CorsConfiguration();
configuration.applyPermitDefaultValues();
configuration.setExposedHeaders(Arrays.asList("Authorization"));
configuration.addAllowedOrigin("*");
configuration.addAllowedMethod("*");
configuration.addAllowedHeader("*");
source.registerCorsConfiguration("/**", configuration);
return source;
}
至于课堂configure
上的方法,WebSecurity
我已经包括了这个:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
我像这样添加我的套接字端点:
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
在前端,我使用一种connect
方法连接到我的 WebSocket:
connect = () => {
const Stomp = require("stompjs");
let SockJS = require("sockjs-client");
SockJS = new SockJS("http://localhost:8080/ws");
stompClient = Stomp.over(SockJS);
stompClient.connect({}, this.onConnected, this.onError);
};
我已尝试将registerStompEndpoints
方法上的 URL 设置为http://localhost:3000
显式设置,但没有效果。还在我package.json
的前端添加了一个代理http://localhost:8080/
,但它仍然给出了同样的错误。我有什么需要做的corsConfigurationSource
才能让这个工作吗?
更新
当我执行以下configure
方法时,它解决了 WebSocket 问题,因为它可以连接到它,但是我无法访问我的应用程序的其他路由,因为它给出了另一个错误。
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/ws").permitAll()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().csrf().disable();
}
另一个错误:
Access to XMLHttpRequest at 'http://localhost:8080/auth/me' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
解决方案
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.antMatchers("/ws/**").permitAll()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().csrf().disable();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setExposedHeaders(Arrays.asList("Authorization"));
configuration.addAllowedOrigin("*");
configuration.addAllowedMethod("*");
configuration.addAllowedHeader("*");
configuration.applyPermitDefaultValues();
source.registerCorsConfiguration("/api/**", configuration);
source.registerCorsConfiguration("/auth/*", configuration);
source.registerCorsConfiguration("/login", configuration);
return source;
}
我最终将其用作我的 WebSecurity。总而言之,我添加.antMatchers("/ws/**").permitAll()
了我的configure
方法。因此,我允许所有请求到达我的 WebSocket 端点,并在我的所有其他路由上显式注册 CORS 配置,但方法/ws
上的路由除外corsConfigurationSource
。希望这可以帮助。
推荐阅读
- docker - 可以运行 Ansible playbook 的 Docker Hub 映像
- python - 说出对非管理员禁用 @everyone 的命令
- objective-c - Objective-c 将参数传递给安装后脚本
- encryption - 什么是 Zip 强加密规范/SecureZip 密钥派生功能?
- c++ - 从字符串中读取数组元素
- google-colaboratory - colab pro + ram 是否有可能不增加
- typescript - 如何在打字稿类型中使一个属性不可选?
- r - 网页抓取返回 R 中的合并句子
- c++ - 在容器上迭代地应用 range-v3 views::filter
- flutter - Flutter 的“NeumorphicToggle”不起作用