WEB 跨域/CORS 验证过程及配置示例
目录
跨域异常
Access to XMLHttpRequest at '' from origin '' 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.
出现以上异常可使用以下工具进行在线测试:
浏览器跨域资源共享(CORS)的验证过程
浏览器的跨域资源共享(CORS)验证过程主要分为简单请求和预检请求两种情况:
1. 简单请求(Simple Request)
满足以下条件的请求被视为简单请求:
- 请求方法为:GET、POST 或 HEAD
- 请求头只包含:Accept、Accept-Language、Content-Language、Content-Type
- Content-Type 的值仅限于:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
验证流程:
- 浏览器直接发送请求,并在请求头中添加 Origin 字段
- 服务器返回响应,需包含以下响应头:
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials(可选)
- Access-Control-Expose-Headers(可选)
2. 预检请求(Preflight Request)
不满足简单请求条件的请求都需要预检,如:
- 使用 PUT、DELETE 等方法
- 发送 JSON 格式数据
- 自定义请求头
验证流程:
- 浏览器首先发送 OPTIONS 请求进行预检
- 包含 Origin 字段
- Access-Control-Request-Method 字段
- Access-Control-Request-Headers 字段(如有自定义头)
- 服务器响应预检请求,返回:
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Max-Age(可选,预检结果缓存时间)
- Access-Control-Allow-Credentials(可选)
- 预检通过后,浏览器发送实际请求
- 实际请求与简单请求的验证流程相同
- 服务器返回实际响应数据
3. 常见响应头说明
- Access-Control-Allow-Origin:允许访问的域名,如 * 或具体域名
- Access-Control-Allow-Methods:允许的请求方法,如 GET, POST, PUT, DELETE
- Access-Control-Allow-Headers:允许的请求头
- Access-Control-Allow-Credentials:是否允许发送 Cookie
- Access-Control-Max-Age:预检请求的有效期
- Access-Control-Expose-Headers:允许浏览器访问的响应头
4. 注意事项
- 如果要发送 Cookie,需要:
- 前端设置 withCredentials = true
- 服务端设置 Access-Control-Allow-Credentials = true
- Access-Control-Allow-Origin 不能设为 *,必须指定具体域名
- 预检请求的缓存:
- 通过 Access-Control-Max-Age 设置缓存时间
- 缓存期内相同请求不再发送预检请求
- 安全考虑:
- 不建议使用 * 通配符
- 建议明确配置允许的域名、方法和请求头
- 对敏感操作要进行身份验证
1、NGINX 配置
server {
listen 80; # 监听的端⼝
server_name localhost; # 域名或ip
location / { # 访问路径配置
#允许跨域请求的域,* 代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
if ($request_method = 'OPTIONS') {
return204;
}
root /usr/share/nginx/html;# 根⽬录
index index.html index.htm; # 默认⾸⻚
}
error_page 500 502 503 504 /50x.html; # 错误⻚⾯
location = /50x.html {
root html;
}
}
2、JAVA 配置
2.1、Spring Boot 注解方式
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class TestController {
// 在控制器类上添加@CrossOrigin注解
// origins = "*" 表示允许所有域名访问
// maxAge = 3600 表示预检请求的有效期为3600秒
}
2.2、全局配置方式
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 CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域访问的路径
.allowedOrigins("*") // 允许跨域访问的源
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允许请求方法
.maxAge(3600) // 预检间隔时间
.allowedHeaders("*") // 允许头部设置
.allowCredentials(true); // 是否发送cookie
}
}
2.3、Spring Security 配置方式
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
// 其他安全配置
.csrf().disable();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
3、PHP 配置
#入口文件处添加
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: *");
4、NODEJS 配置
4.1、nodejs express 配置
//1.导入模块
const express = require('express')
//2.创建服务器
let app = express()
// 导入一个cors(需要下载:这是给响应头设置res.setHeader("Access-Control-Allow-Origin", "*"))
var cors = require('cors')
app.use(cors())
4.2、nodejs koa2 配置
const cors = require('koa2-cors');
const Koa = require('koa');
const app = new Koa();
app.use(cors({
exposeHeaders: ['Authenticate'],
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE', 'PUT', 'PATCH'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}));
curl 测试命令
curl -i -X OPTIONS 'https://****************' \
-voa /dev/null \
-H 'Origin: http://*********(跨域地址)' \
-H "Access-Control-Request-Method: GET(动作)"
WEB 跨域/CORS 配置示例
WEB 跨域/CORS 配置示例 HTTP跨域解决方案|跨域在线调试|CORS在线调试|JAVA|PHP|nodejs|nginx|Access-Control-Allow-Origin|Access-Control-Allow-Headers|Access-Control-Allow-Methods