添加了 corsConfigurationSource 仍然报错 "has been blocked by CORS policy"

Added corsConfigurationSource and still an error "has been blocked by CORS policy"

我正在尝试将 Spring 安全连接到我的项目。 创建了安全配置 class

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtTokenProvider jwtTokenProvider;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    public SecurityConfig(JwtTokenProvider jwtTokenProvider) {
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .cors().and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/auth/api/v1/user/register").permitAll()
                .antMatchers("/auth/api/v1/admin/*").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .apply(new JwtConfigurer(jwtTokenProvider));
    }
}

我正在从浏览器发送注册请求

http://localhost:15001/auth/api/v1/user/register

我得到了答案:

Access to XMLHttpRequest at 'http://localhost:15001/auth/api/v1/user/register' from origin 'http://localhost:4200' 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.

根据 Spring 文档,我添加了 corsConfigurationSource 方法:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtTokenProvider jwtTokenProvider;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    public SecurityConfig(JwtTokenProvider jwtTokenProvider) {
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .cors().and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/auth/api/v1/user/register").permitAll()
                .antMatchers("/auth/api/v1/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .apply(new JwtConfigurer(jwtTokenProvider));
    }
}

我正在从浏览器发送注册请求

http://localhost:15001/auth/api/v1/user/register

我仍然得到同样的错误

Access to XMLHttpRequest at 'http://localhost:15001/auth/api/v1/user/register' from origin 'http://localhost:4200' 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.

为什么错误没有消失?

我知道还有另一种添加控制器的方法

@CrossOrigin(origins="http://localhost:4200″)

您也可以添加到页眉。 但我想弄清楚为什么这个方法不起作用。

pom.xml

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.4.12</version>
    <relativePath/>
</parent>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>${jwt.version}</version>
  </dependency>
  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>${postgres.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
  </dependency>
</dependencies>

这是我形成答案的代码

final UserDto userDto = userToUserDtoConverter.convert(optionalUser.get());
if (password.equals(UserUtils.encryptText(optionalAuth.get().getPassword()))) {
  final HttpHeaders responseHeaders = new HttpHeaders();
  final String token = jwtTokenProvider.createToken(optionalAuth.get().getName());
  return confirmUserRegister(userDto, "Пользователь авторизован",
    HttpStatus.OK, responseHeaders);
}

protected ResponseEntity<DataResponse<UserDto>> confirmUserRegister(
    UserDto userDto, String message, HttpStatus httpStatus, HttpHeaders responseHeaders) {
  final DataResponse<UserDto> response = new DataResponse<>();
  response.setStatus(StatusType.SUCCESSFUL);
  response.setData(userDto);
  response.addMessage(httpStatus.value(), message);
  return new ResponseEntity<>(response, responseHeaders, httpStatus);
}

这里是link项目enter link description here

这个项目还很原始。并且这是项目的副本,所以你可以随意编辑

如果是本地环境,则不需要配置Spring,而是修改angular配置。

在项目的 src/ 文件夹中创建文件 proxy.conf.json

将以下内容添加到新的代理文件中:

{
  "/api": {
    "target": "http://localhost:3000",
    "secure": false
  }
}

在 CLI 配置文件中,angular.json,将 proxyConfig 选项添加到服务目标:

...

"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.json"
    },
...

到运行具有此代理配置的开发服务器,调用ng serve

更多详细信息here。配置 Spring CORS 的问题在于:

  • 您正在尝试解决特定于开发环境的问题
  • 这可能会将 CORS 配置泄漏到不需要它们的生产设置中,除非您实际上想要设置 CORS。

现在,在生产中要做什么?

这实际上取决于您如何捆绑代码。

如果您的 UI + Java 代码将在同一个可部署文件中,WAR 或 JAR,您不需要配置 CORS,因为它们将被部署在同一个文件中域 (https://apps.example.com) 或同一上下文根 (https://apps.example.com/app).

当您的 UI 和 java 代码不在同一个域或您希望将应用程序部署在其他域时, 需要配置 CORS (https://apps.example.**com**) 从他们的页面访问您的 API。

请注意Spring,当你设置

configuration.setAllowCredentials(true);

Spring不接受:

configuration.setAllowedOrigins(Arrays.asList("*"));

您需要像这样一一配置所需的来源:

configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));

你的配置应该是这样的

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers", "Access-Control-Allow-Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", "Origin", "Cache-Control", "Content-Type", "Authorization"));
    configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

你必须用这个更新你的配置方法:

Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .**cors().disable().and().csrf().disable()**
                .
                .
                .
    }