在Spring MVC中进行CORS设置

首先 or 开始

这篇文章总结了在使用Angular和Spring Boot进行SPA开发时,将客户端和服务器端应用程序托管在不同机器上时需要考虑的事项。

    • Same Origin Policy

 

    • Cross-Origin Resource Sharing

 

    • Spring MVC の Cross-Origin Resource Sharing 設定

 

    サーバホスト名解決

我将以以下的四个结构进行解释。

顺便说一句,我们已经发布了应用程序的示例。

同源策略

被翻译为“同一起源政策”。

以下是下面的图表:

    • Angular アプリが https://angular.example.com

Spring Boot アプリが https://boot.example.com

这表示它们在各自运行。

Same Origin Policy.png

在Web浏览器中,访问https://angular.example.com,
下载index.html和js文件,
在Web浏览器中运行Angular应用程序。

在这种情况下,客户端会使用Spring Boot运行的服务器https://boot.example.com进行数据获取的异步通信,但该请求会出现错误。

因此,通过应用同源策略,可以限制从https://angular.example.com加载的脚本文件无法访问https://boot.example.com资源。

这被称为同源策略(Same Origin Policy)。

跨源资源共享

CORS 是跨域资源共享的缩写。

同源策(Same Origin Policy)是构建安全的Web应用程序的重要概念。
然而,当客户端和服务器端需要在不同的机器上运行时,就需要使用跨域资源共享(Cross-Origin Resource Sharing,也称为跨域资源共享)来实现。

基本机制涉及HTTP请求头和HTTP响应头之间的交互。

首先,客户端会设置一个名为”Origin”的请求头并发送请求。该值将被设置为脚本文件的来源,即”https://angular.example.com”。

Origin: https://angular.example.com

然后,服务器接收到请求后,将判断请求头中的Origin值是否合法。
如果合法,服务器将在返回时附加Access-Control-Allow-Origin响应头,并正常返回响应。

Access-Control-Allow-Origin: https://angular.example.com

请参考 MDN web docs 上的“跨源资源共享(CORS)”获取更详细的信息。

Spring MVC 的跨域资源共享设置

Spring MVC 可以轻松配置跨域资源共享。
本次的配置是什么呢?

    • コントローラークラス・メソッドに個別にアノテーションで設定する

 

    Java Configでアプリケーション全体で設定する

我将向您介绍两种方法。

另外,为了简化环境搭建,假设您使用Spring Boot。

在控制器类的方法上单独使用注解进行设置。

我們使用@CrossOrigin註釋。
實際的使用方法如下:

package com.example.server.web.rest;

import com.example.server.service.TaskService;
import com.example.server.web.response.TaskResponse;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/tasks")
public class TaskRestController {

    private final TaskService todoService;

    public TaskRestController(TaskService todoService) {
        this.todoService = todoService;
    }

    @GetMapping
    @CrossOrigin
    public List<TaskResponse> findAll() {
        return this.todoService.findAll().stream().map(todo -> new TaskResponse(todo)).collect(Collectors.toList());
    }
}

給控制器方法添加標註以允許來自不同來源的存取。這樣做可以啟用跨源資源共享。(给控制器方法添加注解以允许来自不同来源的访问。这样做可以启用跨源资源共享。)

但是,默认设置下,允许的源是通配符,也就是允许从全球任何网站生成的脚本发出请求的设置。

您可以使用@CrossOrigin注释的origins属性来设置允许的Origin。

以下给出了具体的方法。

package com.example.server.web.rest;

import com.example.server.service.TaskService;
import com.example.server.web.response.TaskResponse;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/tasks")
public class TaskRestController {

    private final TaskService todoService;

    public TaskRestController(TaskService todoService) {
        this.todoService = todoService;
    }

    @GetMapping
    @CrossOrigin(origins = {"http://localhost:4200"})
    public List<TaskResponse> findAll() {
        return this.todoService.findAll().stream().map(todo -> new TaskResponse(todo)).collect(Collectors.toList());
    }
}

由于接收到的是字符串数组,因此可以设置多个允许的Origin。

请参考官方文档并进行适当的设置,因为还可以施加其他详细的限制。

用Java Config在整个应用程序中进行配置设定。

让我们删除先前在控制器方法中设置的@CrossOrigin注解。

请将下面的Java配置放在Spring Boot的组件扫描有效包中。

package com.example.server.web.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 {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("http://localhost:4200");
    }
}

WebMvcConfigurer是一个用于自定义Spring Web相关配置的接口。
通过添加@Configuration注解并将其配置为Java Config,可以重写方法来自定义配置。

CORS通过addCorsMappings方法将参数CorsRegistry进行设置。

在上述的例子中,原点(Origin)允许接收来自 http://localhost:4200 的设置。

由于可以进行更详细的设置,请参考官方文档并根据要求进行配置。

服务器主机名解析

如果要处理CORS,那么在开发环境中需要

只需要一种选项:在本地环境中运行的话,生产环境中会例如。

需要考虑在运行的环境中的差异。换句话说,开发环境的Angular应用程序需要切换到http://localhost:8080进行异步通信,而生产环境的Angular应用程序需要切换到https://boot.example.com。

由于Angular可以具有特定于环境的配置值,因此我们可以利用它。

在Angular应用程序中,默认情况下,在src/environments目录下有各个环境的配置文件。

キャプチャ.PNG
    • environment.ts :開発環境用

 

    environment.prod.ts :本番環境用

这是配置文件。
默认情况下,

export const environment = {
  production: false
};
export const environment = {
  production: true
};

只有这个被设定。
我将编辑为下列形式。

export const environment = {
  production: false,
  apiUrl: 'http://localhost:8080'
};
export const environment = {
  production: true,
  apiUrl: 'http://boot.example.com'
};

我們將添加 apiUrl 的設定。
因為 production 用於判定是否以開發模式啟動 Angular 應用程式,所以保留它。
接下來,我們將編輯用於執行非同步通訊請求的服務類別。

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';
import {Task} from './task';
import {environment} from "../environments/environment";

@Injectable({
  providedIn: 'root'
})
export class TaskDataService {

  constructor(private http: HttpClient) {
  }

  findAll(): Observable<Task[]> {
    return this.http.get<Task[]>(environment.apiUrl + '/api/tasks');
  }
}

将异步通信的请求URL从环境设置文件中引用。
在使用Angular CLI的ng serve进行执行或者使用无选项的ng build进行构建时,
将应用开发环境的environment.ts应用,
但是如果使用ng build –prod并带有生产环境选项进行构建,
将应用生产环境的environment.prod.ts。

请参考参考书 获取更详细的信息。

只需要一個選項,請把以下內容用中文重述:

充分
補齊

    • Angular CLI :Angularアプリの開発をサポートするコマンドライン

 

    • ng serve :Angular CLIに含まれるAngularアプリの検証サーバ

 

    ng build :Angular CLIに含まれるAngularアプリのビルド機能
广告
将在 10 秒后关闭
bannerAds