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 的 URL 处理问题
使用 Angular 2 和 Spring Boot 发送发布请求
Angular 2 + CORS + 带有 Spring Security 的 Spring Boot Rest Controller