带有 Angular 的 Spring Boot。从源“http://localhost:4200”访问“http://localhost:8080/”的 XMLHttpRequest 已被 CORS
Posted
技术标签:
【中文标题】带有 Angular 的 Spring Boot。从源“http://localhost:4200”访问“http://localhost:8080/”的 XMLHttpRequest 已被 CORS 策略阻止【英文标题】:Spring boot with Angular. Access to XMLHttpRequest at 'http://localhost:8080/' from origin 'http://localhost:4200' has been blocked by CORS policy 【发布时间】:2019-05-27 10:26:24 【问题描述】:我的 Angular 应用程序在 http://localhost:4200 端口上运行,Spring Boot 在 http://localhost:8080 端口上运行。 当我从客户端发出请求时,我收到此错误。
我尝试通过以下方式创建标题:
headers = new HttpHeaders('Access-Control-Allow-Origin' : '*')
然后将 headers 变量放入 PUT 请求中,如下所示:
this.http.put("//localhost:8080/save-account", accountForm,
headers: this.headers).subscribe(
res => console.log(res),
err => console.log(err)
)
但没有任何结果。
我的代码:
服务器端控制器:
package com.tigran.chagmo.controllers;
import com.tigran.chagmo.models.AccountRepository;
import java.util.Collection;
import com.tigran.chagmo.entities.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins="http://localhost:4200")
public class HomeController
@Autowired
AccountRepository accRepo;
@PutMapping("/update-account")
public Account putAccount(@RequestBody Account account)
accRepo.save(account);
return account;
客户端 Typescript 文件。
Angular app.module.ts 文件:
import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import AppRoutingModule from './app-routing.module';
import AppComponent from './app.component';
import Routes, RouterModule from '@angular/router';
import HomeComponent from './home/home.component';
import NotFoundComponent from './not-found/not-found.component';
import SignUpComponent from './sign-up/sign-up.component';
import LinksService from './links/links.service';
import FormsModule from '@angular/forms';
import AccountService from './account-service/account.service';
import HttpClientModule from '@angular/common/http';
const appRoutes: Routes = [
path: '',
component: HomeComponent
,
path: 'home',
component: HomeComponent
,
path: 'sign-up',
component: SignUpComponent
,
path: '**',
component: NotFoundComponent
]
@NgModule(
declarations: [
AppComponent,
HomeComponent,
NotFoundComponent,
SignUpComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot(appRoutes)
],
providers: [
LinksService,
AccountService
],
bootstrap: [AppComponent]
)
export class AppModule
Angular 注册组件 ts 文件:
import Component, OnInit from '@angular/core';
import LinksService from '../links/links.service';
import AccountService from '../account-service/account.service';
@Component(
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
)
export class SignUpComponent implements OnInit
constructor(private links: LinksService,
private accountService: AccountService)
getHome()
this.links.getHome();
save(accountForm: any)
this.accountService.update(accountForm);
ngOnInit()
this.accountService.getAll();
账户服务ts文件:
import Injectable from '@angular/core';
import HttpClient from '@angular/common/http';
@Injectable(
providedIn: 'root'
)
export class AccountService
constructor(private http: HttpClient)
getAll()
return this.http.get("//localhost:8080/accounts")
getOne(id: number)
return this.http.get("//localhost:8080/account/"+id);
update(accountForm: any)
this.http.put("//localhost:8080/save-account",
accountForm).subscribe(
res => console.log(res),
err => console.log(err)
)
注册组件html文件:
<form #accountForm="ngForm" (ngSubmit)="save(accountForm.value)" class="text-center border border-light p-5" >
<label for="gmail" >Gmail</label>
<input
ngModel name="gmail"
id="gmail"
class="form-control mb-4"
tpye="text" >
<label for="name" >Name</label>
<input
ngModel name="name"
id="name"
class="form-control mb-4"
tpye="text" >
<label for="username" >Username</label>
<input
ngModel name="username"
id="username"
class="form-control mb-4"
tpye="text" >
<label for="password" >Password</label>
<input
ngModel name="password"
id="password"
class="form-control mb-4"
tpye="text" >
<label for="repeat-password" >Repeat password</label>
<input
ngModel name="repeat-password"
id="repeat-password"
class="form-control mb-4"
tpye="text" >
<button [disabled]="!accountForm.valid" class="btn btn-info btn-block my-4" >Sign up</button>
<p class="text-left" >Already have an account? <a routerLink=" getHome() " class="text-primary text-right">Log in</a></p>
</form>
通过浏览器填写表格并发送数据后。我收到此错误。
Failed to load resource: the server responded with a status of 403 ()
Access to XMLHttpRequest at 'http://localhost:8080/save-account'
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.
HttpErrorResponse
error: ProgressEvent isTrusted: true, lengthComputable: false, loaded:
0, total: 0, type: "error", …
headers: HttpHeaders normalizedNames: Map(0), lazyUpdate: null,
headers: Map(0)
message: "Http failure response for (unknown url): 0 Unknown Error"
name: "HttpErrorResponse"
ok: false
status: 0
statusText: "Unknown Error"
url: null
__proto__: HttpResponseBase
请帮助我摆脱这个错误并解释为什么会发生。 提前致谢。
【问题讨论】:
【参考方案1】:这对我有用。我刚刚将此 bean 添加到通过 WebMvcConfigurationSupport 扩展的 WebConfig Spring 类中。这里是我的进口商品。
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfiguration;
【讨论】:
【参考方案2】:在 Application.java 中添加这段代码
@Bean
public CorsFilter corsFilter()
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
【讨论】:
【参考方案3】:链接中有两个错误(没有http:
和save-account
而不是update-account
):
this.http.put("//localhost:8080/save-account", accountForm,
headers: this.headers).subscribe(
res => console.log(res),
err => console.log(err)
)
链接应该是
http://localhost:8080/update-account
【讨论】:
我在代码中有@GetMapping("/save-account"),然后将其更改为"/update-account",忘记更改客户端代码。但是它在没有“http:”和标题的情况下工作。你能解释一下“loclahost:8080”和“//loclahost:8080”之间的区别和不放标题吗? 标头的目的是向服务器提供有关传入请求的信息。例如:内容类型(文本、json 或 html)、授权、访问方法等。如果您在服务器上指定这些要求,那么请求者将必须发送适当的标头。至于http:
还是没有。我不确定它是如何工作的。我假设this.http
处理了它。当我使用 https
设置我的 Angular 应用程序时,我遇到了协议问题。然后我所有的网址都必须使用https
。
使用 Postman 之前检查您的服务器应用程序是否运行良好并根据您的设置。 getpostman.com
我想最安全的方法是在 Angular 的 http 方法中明确提及您要使用的协议(http/https)。我有同样的问题,因为我没有提到它并认为是 Spring 问题。这并不直观,因为当您拥有 http.get
时,例如您希望 Angular 负责附加协议。以上是关于带有 Angular 的 Spring Boot。从源“http://localhost:4200”访问“http://localhost:8080/”的 XMLHttpRequest 已被 CORS的主要内容,如果未能解决你的问题,请参考以下文章
带有 Keycloak 的 Angular/Spring Boot 抛出 403
Angular 2 + CORS + 带有 Spring Security 的 Spring Boot Rest Controller
带有spring boot LDAP身份验证的Angular2
如何将带有 angular 2 前端(angular-cli build)的 spring-boot webapp 部署到 Tomcat?