首先要会判断预检请求 还是简单请求
简单请求
预检请求
简单请求条件 是 否 方法限制: GET, HEAD, POST Content-Type 限制 Headers 限制 CORS 请求 是否满足简单请求条件? 简单请求 预检请求 GET HEAD POST with simple Content-Type PUT, DELETE, PATCH等 POST with complex Content-Type 自定义头部 application/x-www-form-urlencoded multipart/form-data text/plain Accept Accept-Language Content-Language Content-Type 仅限于简单值
解释:
-
简单请求:
- 方法:GET, HEAD, POST
- 如果是 POST,Content-Type 仅限于:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 只包含以下头部:
- Accept
- Accept-Language
- Content-Language
- Content-Type(仅限于上述值)
-
预检请求(非简单请求):
- 使用其他 HTTP 方法(如 PUT, DELETE, PATCH 等)
- POST 请求使用其他 Content-Type(如 application/json)
- 包含自定义头部
当然可以。让我们通过流程图和实际例子来解释简单请求和预检请求(非简单请求)的区别。
首先,我们来看两种请求的流程图:
浏览器 服务器 简单请求 发送请求(GET, POST等) 返回响应(带CORS头) 预检请求 发送OPTIONS预检请求 返回预检响应(带CORS头) 发送实际请求 返回响应 中止请求 alt [预检成功] [预检失败] 浏览器 服务器
这个 CORS 配置允许比较宽松的跨域访问。让我们详细分析一下这个配置对应的前端请求类型:
- 创建
StsRequest.java
类:
java
package com.example.demo;
public class StsRequest {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
- 创建
StsResponse.java
类:
java
package com.example.demo;
public class StsResponse {
private String message;
public StsResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 修改主应用类
DemoApplication.java
:
java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
@RequestMapping("/api/gateway/jzgj/app/oss")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:5173"); // 明确指定允许的源
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@PostMapping("/getSts")
public StsResponse getSts(@RequestBody StsRequest request, @RequestHeader("token") String token) {
System.out.println("Received request with id: " + request.getId());
System.out.println("Token: " + token);
return new StsResponse("STS response for id: " + request.getId());
}
}
夜店入口 安保模式选择 普通模式 严格模式 不允许的模式 允许所有人进入
不允许携带身份证件 只允许特定人进入
必须携带身份证件 允许所有人进入
允许携带身份证件 config.addAllowedOrigin('*')
config.setAllowCredentials(false) config.addAllowedOrigin('http://localhost:5173')
config.setAllowCredentials(true) config.addAllowedOrigin('*')
config.setAllowCredentials(true) 安全但开放 安全且可控 不安全! 不被允许
第二部分: UniApp 前端
vue
<template>
<view class="content">
<button @click="getSts">获取 STS</button>
<text v-if="response">响应: {{ response }}</text>
</view>
</template>
<script>
export default {
data() {
return {
response: ''
}
},
methods: {
getSts() {
uni.request({
url: 'http://localhost:9999/api/gateway/jzgj/app/oss/getSts',
method: 'POST',
header: {
'Content-Type': 'application/json',
'token': '806e4f157ab9442dbfa8b33e50a40e26'
},
data: {
id: 1
},
success: (res) => {
this.response = JSON.stringify(res.data);
},
fail: (err) => {
console.error('错误:', err);
this.response = '发生错误';
}
});
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
button {
margin-top: 20px;
}
text {
margin-top: 20px;
}
</style>
浏览器(http://localhost:5173) 服务器(http://192.168.110.233:9999) 发送 OPTIONS 预检请求 CorsFilter 处理预检请求 检查 CORS 政策 CorsConfiguration 定义CORS策略 返回预检响应(带CORS头) 发送实际请求 @PostMapping("/getSts") 处理实际请求 返回响应 中止请求 alt [预检成功] [预检失败] 浏览器(http://localhost:5173) 服务器(http://192.168.110.233:9999)
浏览器 (http://localhost:5173) CorsFilter CorsConfiguration 控制器 发送 OPTIONS 预检请求 获取CORS配置 setAllowCredentials(true) addAllowedOrigin("http://localhost:5173") addAllowedHeader("*") addAllowedMethod("*") 返回CORS配置 应用CORS配置 返回预检响应(带CORS头) 发送实际请求 (POST /getSts) @PostMapping("/getSts") 处理请求 返回响应 中止请求 alt [预检成功] [预检失败] 浏览器 (http://localhost:5173) CorsFilter CorsConfiguration 控制器
应用程序 @Bean方法 UrlBasedCorsConfigurationSource CorsConfiguration CorsFilter 调用corsFilter()方法 创建 UrlBasedCorsConfigurationSource 创建 CorsConfiguration setAllowCredentials(true) 允许发送凭证 addAllowedOrigin("http://localhost:5173") 允许特定源 addAllowedHeader("*") 允许所有头部 addAllowedMethod("*") 允许所有HTTP方法 registerCorsConfiguration("/**", config) 对所有路径应用配置 创建 CorsFilter(source) 返回 CorsFilter 应用程序 @Bean方法 UrlBasedCorsConfigurationSource CorsConfiguration CorsFilter
现在让我们详细解释每一行代码:
-
@Bean public CorsFilter corsFilter() {
- 这是一个 Spring Bean 定义方法,它会在应用启动时被调用,创建一个
CorsFilter
实例。
- 这是一个 Spring Bean 定义方法,它会在应用启动时被调用,创建一个
-
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- 创建一个 URL 基础的 CORS 配置源,用于管理不同 URL 路径的 CORS 配置。
-
CorsConfiguration config = new CorsConfiguration();
- 创建一个新的 CORS 配置对象,用于设置具体的 CORS 规则。
-
config.setAllowCredentials(true);
- 允许跨域请求携带凭证信息(如 cookies)。这对于需要身份验证的请求很重要。
-
config.addAllowedOrigin("http://localhost:5173");
- 明确指定允许的源。这里只允许来自
http://localhost:5173
的请求,提高了安全性。
- 明确指定允许的源。这里只允许来自
-
config.addAllowedHeader("*");
- 允许所有的请求头。
"*"
表示任何头部都被允许。在生产环境中,您可能想要限制具体的头部。
- 允许所有的请求头。
-
config.addAllowedMethod("*");
- 允许所有的 HTTP 方法(GET, POST, PUT, DELETE 等)。同样,
"*"
表示所有方法都允许。
- 允许所有的 HTTP 方法(GET, POST, PUT, DELETE 等)。同样,
-
source.registerCorsConfiguration("/**", config);
- 将 CORS 配置注册到配置源上。
"/**"
表示这个配置适用于所有的路径。
- 将 CORS 配置注册到配置源上。
-
return new CorsFilter(source);
- 创建并返回一个新的
CorsFilter
实例,使用配置好的源。
- 创建并返回一个新的
这个配置的主要目的是:
- 允许来自
http://localhost:5173
的跨域请求 - 允许这些请求携带凭证信息
- 允许所有的请求头和 HTTP 方法
- 将这个配置应用到所有的 API 路径