在尝试从 React 前端访问 Spring Boot 应用程序中的某些端点时,我遇到了 CORS(跨源资源共享)问题。我已在 Spring Boot 应用程序中配置了 CORS,但它似乎仅适用于不需要身份验证的端点。
问题: 我可以成功访问 /login 和 /register 端点,这些端点配置为允许所有请求。但是,当我尝试访问经过身份验证的端点(例如 /hello)时,我在浏览器控制台中收到以下 CORS 错误:
从源“http://localhost:3000”访问“http://localhost:8080/trader/hello”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否“ Access-Control-Allow-Origin' 标头存在于请求的资源上。
安全配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
UserDetailsService userDetailsService;
@Autowired
JwtFilter jwtFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(req -> req
.requestMatchers("/trader/register", "/trader/login").permitAll()
.requestMatchers("admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(new BCryptPasswordEncoder());
provider.setUserDetailsService(userDetailsService);
return provider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns(CorsConfiguration.ALL) // Allow all origins (can be replaced with your frontend URL)
.allowedMethods(CorsConfiguration.ALL)
.allowCredentials(true) // Allow credentials (cookies, HTTP auth)
.allowedHeaders(CorsConfiguration.ALL);
}
};
}
}
我的控制器代码:
@RestController
@RequestMapping("/trader")
public class TraderController {
@Autowired
TraderService traderService;
@GetMapping("/hello")
public Map<String, String> sayHello(Principal principal) {
Map<String, String> res = new HashMap<>();
res.put("Message", "Hello");
return res;
}
}
用于获取数据的反应代码:
export default async function fetchHello() {
try {
const response = await fetch("http://localhost:8080/trader/hello", {
method: "GET",
headers: {
"Authorization": `Bearer YOUR_TOKEN_HERE`, // Use the appropriate bearer token here
"Content-Type": "application/json"
}
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchHello();
要点:
问题很可能与您正在使用
http://localhost:8080/trader/hello
和/或在 vite.config 中缺少代理设置有关。
将
http://localhost:8080/trader/hello
替换为 /trader/hello
验证 vite.config 看起来像这样:
import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
proxy: {
"/trader": { // you might want to adjust this
target: "http://localhost:8080",
changeOrigin: true,
secure: false
}
}
}
})