使用 React 前端的 Spring Boot 中的 CORS 策略问题

问题描述 投票:0回答:1

在尝试从 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();

要点:

  1. 该问题不是由硬编码的不记名令牌引起的;每次我的服务器用新的有效令牌响应时,我都会更改令牌,这在我的 JavaScript 文件和 Postman 中工作得很好。
  2. 唯一正常工作的端点是 /login 和 /register,它们被设置为允许所有请求。任何经过身份验证的端点都会抛出 CORS 错误。
reactjs spring-boot cors vite
1个回答
0
投票

问题很可能与您正在使用

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
            }
        }
    }
})
© www.soinside.com 2019 - 2024. All rights reserved.