【问题标题】:Cors enabled in Spring Boot with Angular, still cors errors在带有 Angular 的 Spring Boot 中启用了 Cors,但仍然出现 cors 错误
【发布时间】:2021-03-01 16:37:07
【问题描述】:

我为所有来源和标头启用了 cors,但是当我从我的 angular 应用程序调用 get 方法到 spring boot 时,我仍然收到 cors 错误。

来自控制台的 Cors 错误:

Access to XMLHttpRequest at 'http://localhost:8080/api/users/test@ronny.nl' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我的controller(我叫getbyemail):

@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
@RequestMapping(value = "/api/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(final UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public List<UserDTO> getAllUsers() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public UserDTO getUser(@PathVariable final Long id) {
        return userService.get(id);
    }

    @CrossOrigin(origins = "*", allowedHeaders = "*")
    @GetMapping("/{email}")
    public UserDTO getUserByMail(@PathVariable String email) {
        return userService.getByEmail(email);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Long createUser(@RequestBody @Valid final UserDTO userDTO) {
        return userService.create(userDTO);
    }

    @PutMapping("/{id}")
    public void updateUser(@PathVariable final Long id, @RequestBody @Valid final UserDTO userDTO) {
        userService.update(id, userDTO);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable final Long id) {
        userService.delete(id);
    }

}

我从我的 Angular 应用中调用 get 的地方:

onSubmit(): void {
    this.submitted = true;
    this.wrongInput = false;
    this.loginService.getLogin<User>(this.loginForm.value.email).subscribe((response) => {
      this.tempUser = response;
      console.log(this.tempUser);
      if (this.loginForm.value.email === this.tempUser.email && this.loginForm.value.password === this.tempUser.password) {
        this.localStorageService.save(this.tempUser);
        this.router.navigate(['/home']);
        console.log(true);
      }
      else {
        this.wrongInput = true;
      }
    });
  }

我也尝试添加DevCorsConfiguration

package com.team13.triviaquiz.triviaquizserver.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@Profile("development")
public class DevCorsConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**").allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS");
    }
}

并在我的application.properties 中添加了个人资料:

application.properties
spring.profiles.active=development
#enabling h2 console
spring.h2.console.enabled=true
#fixed URL for H2 (necessary from Spring 2.3.0)
spring.datasource.url=jdbc:h2:mem:triviaquizserver
#turn statistics on
spring.jpa.properties.hibernate.generate_statistics = true
logging.level.org.hibernate.stat=debug
#show all queries
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type=trace

但还是没有运气......

【问题讨论】:

    标签: angular spring-boot cors


    【解决方案1】:

    在您的控制器上尝试以下操作

    @CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*", exposedHeaders = "If-Match")
    

    【讨论】:

    • 然后我得到另一个错误:当 allowCredentials 为真时,allowedOrigins 不能包含特殊值“*”,因为它不能在“Access-Control-Allow-Origin”响应标头上设置。要允许一组来源的凭据,请明确列出它们或考虑改用“allowedOriginPatterns”。
    • 我能够通过在 WebSecurityConfig 上使用 addAllowedOriginPattern(*) 来解决此问题。
    【解决方案2】:

    cors 错误来自为我的两个 get 方法处理不明确的处理程序错误。 我的controller 中有两个get 方法,一个是integer,另一个是String。所以它无法真正弄清楚解析字符串或 int(我认为)我已将 get 方法的 bot 路径更改为:

     @GetMapping("/id/{id}")
        public UserDTO getUser(@PathVariable final Long id) {
            return userService.get(id);
        }
    
        @GetMapping("/email/{email}")
        public UserDTO getUserByMail(@PathVariable String email) {
            return userService.getByEmail(email);
        }
    

    这也修复了 @CrossOrigin(origins = "*", allowedHeaders = "*") 的 cors 错误 在controller

    【讨论】:

      【解决方案3】:

      这可能是由于 Spring 库的更改,从而影响了 Spring Boot 2.4.0。 看这里https://github.com/spring-projects/spring-framework/issues/26111 及其相关票证https://github.com/spring-projects/spring-framework/pull/26108

      编辑 这是来自第一个链接的原始消息:

      #25016 引入了除了 allowedOrigins 之外还可以配置 allowedOriginPatterns 的功能。它让您定义更灵活 模式,而后者实际上是返回的值 Access-Control-Allow-Origin 标头,并且不允许使用“*” 与 allowCredentials=true 组合。引入的变化 WebMvc 和 WebFlux 中的等效 allowedOriginPatterns 方法 config,但不在 SockJS 配置和 AbstractSocketJsService 中。

      我将为 5.3.2 添加这些内容。然后你需要切换到 allowedOriginPatterns 而不是 allowedOrigins 但这会给你一个 更精确地定义允许的域模式的选项。在里面 同时,您可以通过列出特定的 域,如果可行的话。

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
      • 有道理,编辑了答案。谢谢提示
      【解决方案4】:

      这个问题背后的原因在answer中已经明确提到了,简单地说CorsRegistry#allowCredentials(true)不能与默认值CorsRegistry#allowedOrigins()一起使用(默认情况下,如果您没有设置此属性,则允许所有来源,除非任何CorsRegistry#allowedOriginPatterns() 已设置)

      • 用最典型的 Spring boot corsMappings 阐明问题:
          @Bean
          public WebMvcConfigurer corsConfigurer() {
              return new WebMvcConfigurer() {
                  @Override
                  public void addCorsMappings(CorsRegistry registry) {
                      registry.addMapping("/**").allowedMethods("*").allowCredentials(true);
                  }
              };
          }
      

      在上面的例子中allowCredentials被设置为true,同时allowedOrigins没有被配置,这意味着默认情况下所有的来源都是允许的(allowedOrigins的值将是*)。

      • 要解决此问题,您必须明确设置allowedOriginsallowedOriginPatterns。 在下面的代码 sn-p 中,使用了 allowedOriginPatterns,并将值设置为 -> "https://*.domain.com"。此通配符模式匹配来自 domain.com 的任何主机和诸如 https:microservice.division.domain.com 之类的 url 模式
          @Bean
          public WebMvcConfigurer corsConfigurer() {
              return new WebMvcConfigurer() {
                  @Override
                  public void addCorsMappings(CorsRegistry registry) {
                      registry.addMapping("/**").allowedMethods("*").allowedOriginPatterns("https://*.domain.com");
                  }
              };
          }
      
      

      完整代码sn -p link

      【讨论】:

        【解决方案5】:

        我收到错误时的情景是:

        我已经在我的 Spring Boot 服务器应用程序中添加了 Spring Boot 安全依赖项。

        与您的跟踪类似,我添加了 CrossOrigin() 注释来解决问题。但问题并没有得到解决。

        我通过在请求的标头选项中添加基本身份验证解决了这个问题。

        在header中添加基本认证请参考帖子:

        Angular 6 HTTP Get request with HTTP-Basic authentication

        import { HttpHeaders } from '@angular/common/http';
        
        const httpOptions = {
        headers: new HttpHeaders({
        'Content-Type':  'application/json',
        'Authorization': 'Basic ' + btoa('username:password')
        })
        };
        

        用您的用户名和密码替换用户名和密码。 默认情况下,Spring boot 中的用户名是“user”,密码将在启动 Spring Boot 应用程序的控制台上生成。

        注意:您还必须将 CrossOrigin Annotation 添加到您的 RequestMapping 中。

        由于您使用的是基本身份验证,您应该添加 WebSecurityConfiguration 以允许安全配置如下:

        @EnableWebSecurity
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
            
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
                http.cors();
            }
        }
        

        参考资料:

        希望解决方案对您有所帮助。

        谢谢 昌都

        【讨论】:

          【解决方案6】:

          更改corsConfiguration.setAllowedOrigins("*") corsConfiguration.setAllowedOriginPatterns("*") 为我成功了!

          所以基本上是setAllowedOriginssetAllowedOriginPatterns

          【讨论】:

            【解决方案7】:

            你应该创建一个名为“”的类,代码如下

            package com.api.juego.config;
            
            import org.springframework.context.annotation.Configuration;
            import org.springframework.web.servlet.config.annotation.CorsRegistry;
            import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
            
            @Configuration
            public class WebMvcConfig implements WebMvcConfigurer {
            
                private final long MAX_AGE_SECS = 3600;
            
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
                    .allowedHeaders("*")
                    .allowCredentials(false)
                    .maxAge(MAX_AGE_SECS);
                }
            }
            

            出于安全原因,允许的方法是 GET、POST、PUT、PATCH、DELETE 和 OPTIONS。

            【讨论】:

              猜你喜欢
              • 2017-04-29
              • 2021-09-21
              • 2020-01-01
              • 2020-06-22
              • 2019-11-29
              • 2021-11-09
              • 2020-03-12
              • 2020-02-07
              • 2021-03-28
              相关资源
              最近更新 更多