Spring Boot Cors 配置。我在我的 React 应用程序上收到 401

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

这是我第一次使用 springboot,我遇到了 cors 配置的问题。 我尝试了很多事情,但我似乎总是得到: 从源“http://localhost:3000”获取“http://localhost:52700/greeting-javaconfig”的访问已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有HTTP 状态正常。

这个错误我已经有一周左右的时间了,我已经使用了具有许多属性的 cors 配置文件,但我似乎无法使其工作

我使用以下代码在我的配置文件夹中创建了一个 CorsConfig.java 文件:

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;



@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*") // Allow requests from any origin
                .allowedMethods("GET", "POST", "PUT", "DELETE") // Allowed HTTP methods
                .allowedHeaders("*"); // Allowed headers
    }

    @Bean
    CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");


        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

它对我来说看起来很标准,我看到很多例子都使用这种或多或少相同的格式

而且我还注意到我需要一些示例中的 cors 过滤器,因此我在注意到没有它仍然无法工作后也将其添加到项目中:

package com.example.config;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Component
public class CorsFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        exchange.getResponse().getHeaders().add("Access-Control-Allow-Origin", "*");
        exchange.getResponse().getHeaders().add("Access-Control-Allow-Methods", "GET, PUT, POST,                       DELETE, OPTIONS");
        exchange.getResponse().getHeaders().add("Access-Control-Allow-Headers", "Content-Type, Authorization");
        exchange.getResponse().getHeaders().add("Access-Control-Max-Age", "3600");
        return chain.filter(exchange);
    }

}

当使用调试器和邮递员测试此代码时,我得到响应,并且断点将抛出此过滤器函数。

我也有基本的身份验证,我不知道这对问题是否重要,但无论如何我都会使用控制器添加我的代码,以防万一我没有遗漏任何重要信息。

SecurityConfig.java:

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring()
                // Spring Security should completely ignore URLs starting with /resources/
                .requestMatchers("/**");
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests().requestMatchers("/**").permitAll().anyRequest()
                .hasRole("USER").and()
                .formLogin()
                .permitAll();
        http.cors().disable();

        return http.build();
    }
    @Bean
    public MapReactiveUserDetailsService userDetailsService() {
        UserDetails user = User
                .withUsername("user1")
                .password("{noop}user1Pass")  // {noop} for plain text, consider a password encoder for production
                .roles("USER")
                .build();
        return new MapReactiveUserDetailsService(user);
    }

}

基础控制器:

package com.example.controller;
import com.makalu.makaluapi.models.Greeting;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.atomic.AtomicLong;

@RestController
public class BaseController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @CrossOrigin(origins = "http://localhost:3000/")
    @GetMapping("/greeting-javaconfig")
    public Greeting greeting(@RequestParam(required = false, defaultValue = "World") String name) {
        System.out.println("==== get greeting ====");
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }
}

尝试让它发挥作用确实令人沮丧,但这仍然是一个有趣且重要的话题。我将不胜感激有关此主题的任何信息,谢谢!

这也是我用于 api 调用的代码,我尝试过:

const url = 'http://localhost:52700/greeting-javaconfig';

    username = 'user1';
    password = 'user1Pass';

    const credentials = btoa(username + ':' + password);

    const options = {
            method: 'GET',
            headers: {
                'Authorization': 'Basic ' + credentials,
                'Content-Type': 'application/json',
                'Accept': 'text/html',
                'cache-control': 'no-cache'
            },
            // credentials: 'same-origin'
        };

    // @ts-ignore
    fetch(url, options).then(response => {
        console.log(response.body);
    })

有关更多上下文,我还可以运行此curl请求:

curl -v -u user1:user1Pass -H "Access-Control-Request-Method: GET" -H "Origin: http://localhost:3004" -X GET http://localhost:52700/greeting-javaconfig

并得到这个输出:

Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying 127.0.0.1:52700...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 52700 (#0)
* Server auth using Basic with user 'user1'
> GET /greeting-javaconfig HTTP/1.1
> Host: localhost:52700
> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
> User-Agent: curl/7.68.0
> Accept: */*
> Access-Control-Request-Method: GET
> Origin: http://localhost:3004
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS
< Access-Control-Allow-Headers: Content-Type, Authorization
< Access-Control-Max-Age: 3600
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Content-Type-Options: nosniff
< X-Frame-Options: DENY
< X-XSS-Protection: 0
< Referrer-Policy: no-referrer
< Content-Type: application/json
< Content-Length: 34
< Date: Tue, 16 Apr 2024 08:43:30 GMT
<

我不知道它是否重要,但无论如何我都会添加它以获取更多上下文。

我原本期望得到 200OK,但在客户端中未经授权得到 401,但在邮递员中我得到 200OK 和返回值。

java spring-boot cors http-status-code-401
2个回答
0
投票

几天前我遇到了类似的问题,浏览器工具控制台向我显示了 Cors CrossOrigin 的错误,我开始查看与此相关的所有内容。几天后我意识到问题不在 CORS 上,问题是防火墙阻止了端口 8085 的访问,因此控制台显示 CORS 错误。

检查您是否正在访问正确的端口,并且没有防火墙阻止访问,在这里您可以找到类似的错误,CORS有时可能非常通用。无论如何我希望它对你有帮助!


0
投票

将凭据与

Access-Control-Allow-Origin: *
结合使用会导致问题,请参阅 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

请在 CORS 配置中指定您的已知来源,即

http://localhost:3000
而不是星号。

© www.soinside.com 2019 - 2024. All rights reserved.