1、什么是请求跨域(CORS)
请求跨域(Cross-Origin Resource Sharing, CORS)是浏览器的一种安全策略,它限制了一个源(origin)的文档或脚本如何与另一个源的资源进行交互。这里的“源”是由协议(如 http 或 https)、域名(如 example.com)和端口号(如 :80 或 :443)三部分组成的。浏览器的同源策略(Same-Origin Policy)阻止了一个文档或脚本尝试从不同的源加载或提交数据,除非显式地通过 CORS 机制来允许跨源请求。
CORS 允许服务器显式地指定哪些源(域、协议和端口)可以访问其资源。如果客户端(如浏览器)发起了一个跨域的 HTTP 请求(如 AJAX 请求),浏览器会先向目标服务器发送一个预检请求(通常是 OPTIONS 请求),询问是否允许跨域请求。服务器响应这个预检请求时,会在响应头中包含一些特定的 CORS 相关的头部字段,以指示哪些源被允许访问资源。
如下是浏览器的控制台提示的请求跨域:
2、解决跨域问题
在 Spring Boot 项目中解决跨域问题,主要可以通过以下几种方式来实现。
2.1 使用 @CrossOrigin 注解
使用 @CrossOrigin 注解,是 Spring 4.2 后引入的。这是解决跨域问题最直接和简单的方法,@CrossOrigin 注解可以添加到类或者方法上,以允许跨域请求。
【实例】在 Controller 控制器类中,使用 @CrossOrigin 注解,解决跨域问题。
package com.pjb.pm.controller;
import com.pjb.pm.entity.UserInfo;
import com.pjb.pm.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 用户信息控制器
* @author pan_junbiao
**/
@RestController
@RequestMapping("/user")
@CrossOrigin // 核心代码:使用 @CrossOrigin 注解,解决跨域问题
public class UserController
{
@Autowired
private IUserService userService;
/**
* 查询用户信息
*/
@RequestMapping(value = "/getUserInfo/{id}", method = RequestMethod.GET)
public UserInfo getUserInfo(@PathVariable("id") Long userId)
{
UserInfo userInfo = userService.getUserInfo(userId);
return userInfo;
}
}
2.2 重写 WebMvcConfigurer 配置接口
通过实现 WebMvcConfigurer 接口,并重写 addCorsMappings 方法来实现解决跨域问题,这种方式提供了更灵活的配置选项,实现全局的跨域配置。
关于 WebMvcConfigurer 配置接口的详解,请求点击浏览文章:《SpringBoot中的WebMvcConfigurer配置接口的详解》
【实例】在 config 目录下,创建 CorsConfig 类,实现 WebMvcConfigurer 接口,并重写 addCorsMappings 方法来实现解决跨域问题。
package com.pjb.pm.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 解决HTTP请求跨域问题
* @author pan_junbiao
**/
@Configuration
public class CorsConfig implements WebMvcConfigurer
{
@Override
public void addCorsMappings(CorsRegistry registry)
{
registry.addMapping("/**") //添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
.allowCredentials(true) //是否允许发送Cookie信息
.allowedOriginPatterns("*") //开放哪些ip、端口、域名的访问权限
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) //开放哪些Http方法,允许跨域访问
.allowedHeaders("*") //允许HTTP请求中的携带哪些Header信息
.exposedHeaders("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
}
}
2.3 配置 CorsFilter 过滤器
通过自定义 CorsFilter 过滤器,此实现方式和上一种实现方式类似,它也可以实现全局跨域。
package com.pjb.pm.filter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 自定义 CorsFilter 过滤器,解决跨域问题
* @author pan_junbiao
**/
@Configuration
public class GlobalCorsFilter
{
@Bean
public CorsFilter corsFilter()
{
// 1、创建 CORS 配置对象
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*"); // 支持所有域
config.addAllowedHeader("*"); // 支持所有头部
config.addAllowedMethod("*"); // 支持所有请求方式
config.setAllowCredentials(true); // 允许携带凭证,是否发送 Cookie
// 2、添加地址映射
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", config);
// 3、返回 CorsFilter 对象
return new CorsFilter(corsConfigurationSource);
}
}