【问题标题】:Spring boot with Angular. Access to XMLHttpRequest at 'http://localhost:8080/' from origin 'http://localhost:4200' has been blocked by CORS policy带有 Angular 的 Spring Boot。从源“http://localhost:4200”访问“http://localhost:8080/”的 XMLHttpRequest 已被 CORS 策略阻止
【发布时间】: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

请帮助我摆脱这个错误并解释为什么会发生。 提前致谢。

【问题讨论】:

    标签: java angular spring-boot


    【解决方案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 负责附加协议。
        猜你喜欢
        • 2019-10-31
        • 2020-01-26
        • 2021-10-05
        • 2021-08-14
        • 2020-07-09
        • 1970-01-01
        • 2019-11-17
        • 2021-01-20
        • 1970-01-01
        相关资源
        最近更新 更多