angular 9 和 spring boot 2 中请求的资源上不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】angular 9 和 spring boot 2 中请求的资源上不存在“Access-Control-Allow-Origin”标头【英文标题】:No 'Access-Control-Allow-Origin' header is present on the requested resource in angular 9 and spring boot 2 【发布时间】:2020-10-18 19:55:18 【问题描述】:

我在 Spring Boot 应用程序中添加了 Spring Security,并且无论用户是否登录,我都有一些 API 端点需要调用。(我的意思是这些是我需要在前端检索数据的其余端点角度)。

所以,我将其配置为:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
 
    @Autowired
    private UserDetailsService customUserDetailsService;
 
 
    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    
 
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
        auth
         .userDetailsService(customUserDetailsService)
         .passwordEncoder(passwordEncoder());
    
 
    @Override
    protected void configure(HttpSecurity http) throws Exception 
    
           http.csrf().
           disable()
               .authorizeRequests()
               .antMatchers(HttpMethod.OPTIONS, "/**")
               .permitAll()
              .antMatchers("/books").permitAll()
            .antMatchers("/api/v1/search/**").permitAll()
            .antMatchers("/admin/**").hasRole("ADMIN")
               .anyRequest()
               .authenticated()
               .and()
               .httpBasic();
              
    
 

我所有的 api 都暴露自:http://localhost:8080/api/v1/,比如:

http://localhost:8080/api/v1/books
http://localhost:8080/api/v1/bookcategory

我已经使用.antMatchers("/api/v1/search/**") 进行了配置,我的restendpoint 配置是:

@RequestMapping("/api/v1")
@RestController
@CrossOrigin(origins ="http://localhost:4200")
public class BasicAuthController 

    @GetMapping(path = "/basicauth")
    public AuthenticationBean basicauth() 
        System.out.println("hitted here");
        return new AuthenticationBean("You are authenticated");
    
    
  

我允许 csfr 政策使用:

@Configuration
public class RepositoryConfig implements RepositoryRestConfigurer

    @Autowired
    private EntityManager entityManager;
    
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) 
        config.exposeIdsFor(entityManager.getMetamodel().getEntities().stream()
                .map(Type::getJavaType).toArray(Class[]::new));
        
        
        //to handle cross origin
        config.getCorsRegistry().addMapping("/**").allowedOrigins("http://localhost:4200");
    

BookRepository.java

public interface BookRepository extends JpaRepository<Book,Long> 

    @RestResource(path = "categoryid")
    Page<Book>  findByCategoryId(@Param("id") Long id,Pageable pageable);
    
    //to get book by searching
    @RestResource(path = "searchbykeyword")
    Page<Book>  findByNameContaining(@Param("xyz") String keyword,Pageable pageable);

正面我有角 9 为:

auth.service.ts

import  Injectable  from '@angular/core';
import  HttpClient  from '@angular/common/http';
import  map  from 'rxjs/operators';

@Injectable(
  providedIn: 'root'
)
export class AuthService 

   // BASE_PATH: 'http://localhost:8080'
   USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser';

   public username: String;
   public password: String;
 
   constructor(private http: HttpClient) 
 
   
 
   authenticationService(username: String, password: String) 
     return this.http.get(`http://localhost:8080/api/v1/basicauth`,
        headers:  authorization: this.createBasicAuthToken(username, password)  ).pipe(map((res) => 
         this.username = username;
         this.password = password;
         this.registerSuccessfulLogin(username, password);
       ));
   
 
   createBasicAuthToken(username: String, password: String) 
     return 'Basic ' + window.btoa(username + ":" + password)
   


//我没有粘贴所有代码。

所以,当我转到链接 http://localhost:4200/books 时出现错误:

【问题讨论】:

您能否尝试使用邮递员的localhost:8080/api/...OPTIONS 方法,看看是否返回了Access-Control-Allow-Origin 标头,它的值是localhost:4200*,阅读更多这里developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS 我在邮递员中试过这个:curl -X OPTIONS localhost:8080/api/v1/books -i 我得到了无法得到任何回应 你确定你从角度调用的这个端点是正确的吗?我一直在使用 angular+springboot,我意识到当 angular 找不到目的地时,浏览器会发送一个 CORS 错误 是的,当我从 Angular 发送用户名和密码时,登录成功发生,当我在浏览器上点击其余端点时,我看到了数据,但是当这些目标链接被称为 CSRF 策略时api 正在从角度获取 如果在使用 OPTIONS 时没有得到响应,这意味着你没有配置你的 API 来捕捉这个方法,你必须添加它 【参考方案1】:

我有一些项目使用具有安全性的 Angular+SpringBoot,我创建了一个特定的 Bean 来处理 CORS,我从来没有遇到过问题。如果您可以尝试,请在您的 WebSecurityConfig 类中添加以下方法:

@Bean
CorsConfigurationSource corsConfigurationSource() 
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200", "http://localhost:8080"));
    configuration.setAllowedMethods(Arrays.asList("GET", "PUT", "POST","OPTIONS", "DELETE"));
    configuration.setAllowedHeaders(Arrays.asList("authorization","content-type"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;

【讨论】:

我应该导入哪个包,cors 或 .cors.reactive? 导入 org.springframework.web.cors.CorsConfiguration;导入 org.springframework.web.cors.CorsConfigurationSource;导入 org.springframework.web.cors.UrlBasedCorsConfigurationSource; 使用这个bean你不需要在控制器中使用@CrossOrigin注解 仍然是同样的错误 从源 'localhost:4200' 访问 XMLHttpRequest 在 'localhost:8080/api/v1/book-category' 已被 CORS 策略阻止:没有 'Access-Control-Allow-Origin' 标头存在请求的资源。 我认为您没有调用正确的端点地址。尝试删除 Spring Security 库并再次调用此端点。也许你会收到同样的错误。正如我之前所说,我意识到有时当浏览器找不到正确的目的地时,它会显示 CORS 错误【参考方案2】:

问题在于 CORS,它是您浏览器的一项安全功能。它确保只能访问来自同一域(和端口!)的资源。您的 Angular 开发服务器和 Tomcat 在不同的端口上运行,这会导致请求被拒绝。您必须配置 CORS。但是,您应该知道自己在做什么,因为您基本上是在禁用安全功能。通常这不是问题。您可以通过将注解 @CrossOrigin 添加到控制器方法或使用 Java 配置来做到这一点。对于第二个原因,我相信你很容易在 Google 上找到它:)

【讨论】:

我已将@crossorigin 添加到每个休息端点,但它仍然无法正常工作【参考方案3】:

CORS(跨域资源共享)是您浏览器的一项安全功能,可防止授权网站使用来自其他来源的资源

简而言之,如果您的站点位于 x:y 来源并从 a:y、x:b 或 a:b 来源(不同的端口和/或域)请求资源,则会发生这种情况

在这种情况下究竟会发生什么

如果您从另一个来源发出 get(或 post...)请求,浏览器将首先向同一端点发出 option 请求,如果它成功并且具有所有允许的标头,它将发出 get 请求,如果不是,它会抛出错误,说明它被拒绝的原因并且不发出原始请求

所以我们现在有两种情况,要么只在获取请求时返回标头,而不是选项之一,要么永远不会返回

【讨论】:

以上是关于angular 9 和 spring boot 2 中请求的资源上不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Angular 9 登录页面连接到 Spring Boot 应用程序?

如何使用spring boot和angular 2登录

Spring Boot + Angular 2 结构

Spring Boot 和 Angular 2 的 URL 处理问题

使用 Angular 2 和 Spring Boot 发送发布请求

Angular 2 + CORS + 带有 Spring Security 的 Spring Boot Rest Controller