CORS案例

wen java案例 1

本文目录导读:

  1. 案例一:最基本的前后端分离
  2. 案例二:指定域名 + 凭据
  3. 案例三:动态多域名支持
  4. 案例四:携带JWT Token的请求
  5. 案例五:完整的前端错误处理
  6. 案例六:使用第三方库(cors包)
  7. 调试技巧
  8. 常见问题快速参考

我来给你提供几个典型的CORS(跨域资源共享)案例,从简单到复杂,帮助你理解各种场景。

最基本的前后端分离

场景

前端运行在 http://localhost:3000,后端API运行在 http://localhost:8080

问题

浏览器发起请求时出现CORS错误。

后端解决方案(Node.js/Express)

// 最简单的CORS配置
const express = require('express');
const app = express();
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});
app.get('/api/data', (req, res) => {
  res.json({ message: 'CORS配置成功!' });
});
app.listen(8080);

指定域名 + 凭据

场景

  • 前端:https://www.myapp.com
  • 后端:https://api.myapp.com
  • 需要携带Cookie

配置(重点)

app.use((req, res, next) => {
  // 只允许特定域名访问
  res.header('Access-Control-Allow-Origin', 'https://www.myapp.com');
  // 允许携带凭证(Cookie)
  res.header('Access-Control-Allow-Credentials', 'true');
  // 允许的请求头
  res.header('Access-Control-Allow-Headers', 
    'Content-Type, Authorization, X-Custom-Header');
  // 允许的请求方法
  res.header('Access-Control-Allow-Methods', 
    'GET, POST, PUT, DELETE, PATCH, OPTIONS');
  // 预检请求缓存时间(秒)
  res.header('Access-Control-Max-Age', '86400');
  // 处理预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});

动态多域名支持

场景

多个前端域名需要访问同一个API。

解决方案

const express = require('express');
const app = express();
// 允许的域名白名单
const allowedOrigins = [
  'https://www.myapp.com',
  'https://admin.myapp.com',
  'http://localhost:3000'
];
app.use((req, res, next) => {
  const origin = req.headers.origin;
  // 检查请求来源是否在白名单中
  if (allowedOrigins.includes(origin)) {
    res.header('Access-Control-Allow-Origin', origin);
    res.header('Access-Control-Allow-Credentials', 'true');
  }
  res.header('Access-Control-Allow-Headers', 
    'Content-Type, Authorization');
  res.header('Access-Control-Allow-Methods', 
    'GET, POST, PUT, DELETE, PATCH, OPTIONS');
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});
// 业务接口
app.get('/api/users', (req, res) => {
  res.json({ users: ['Alice', 'Bob', 'Charlie'] });
});
app.listen(8080);

携带JWT Token的请求

场景

前端需要发送带Authorization头部的请求。

前端代码

// fetch 请求
fetch('https://api.myapp.com/api/private-data', {
  method: 'GET',
  credentials: 'include', // 如果使用Cookie
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  }
});
// axios 请求
axios.get('https://api.myapp.com/api/private-data', {
  withCredentials: true, // 如果使用Cookie(改为withCredentials,而非credentials)
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

后端响应头

res.header('Access-Control-Allow-Origin', 'https://myapp.com');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Expose-Headers', 'Authorization');

完整的前端错误处理

场景

前端正确处理CORS错误和响应。

async function fetchData() {
  try {
    const response = await fetch('https://api.myapp.com/api/data', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ type: 'test' })
    });
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    console.log('成功获取数据:', data);
  } catch (error) {
    if (error instanceof TypeError) {
      console.error('CORS错误或网络错误:', error.message);
      // 具体判断是否是CORS错误
      if (error.message.includes('Failed to fetch')) {
        showCorsErrorMessage();
      }
    } else {
      console.error('其他错误:', error.message);
    }
  }
}
function showCorsErrorMessage() {
  alert('跨域请求失败:请检查服务器CORS配置');
}

使用第三方库(cors包)

最优雅的解决方案

const express = require('express');
const cors = require('cors');
const app = express();
// 配置选项
const corsOptions = {
  origin: function (origin, callback) {
    // 定义允许的来源列表
    const whitelist = [
      'https://myapp.com',
      'https://admin.myapp.com'
    ];
    // 允许无来源的请求(如移动应用、Postman等)
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('不允许的来源'));
    }
  },
  credentials: true, // 允许携带Cookie
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  maxAge: 86400 // 预检请求缓存24小时
};
// 全局应用
app.use(cors(corsOptions));
// 或对特定路由应用
app.get('/api/special', cors(corsOptions), (req, res) => {
  res.json({ message: '这是受CORS保护的接口' });
});
app.listen(8080);

调试技巧

使用Chrome开发者工具

  • 打开Console查看错误信息
  • 在Network中查看请求的Headers

CORS案例

快速诊断方法

// 检查Response Headers中是否有:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

常用测试工具

  • Postman (不会触发CORS,但可测试API功能)
  • chrome 的 cors 插件
  • curl 命令

常见问题快速参考

错误信息 问题原因 解决方案
"No 'Access-Control-Allow-Origin' header is present" 后端未配置CORS 后端添加CORS头
"Request header field authorization is not allowed" 跨域预检失败 允许对应头部
Credentials mode is 'include'" 携带Cookie问题 配置credentials
"Network Error" 网络或CORS问题 检查网络和CORS配置

这些案例覆盖了绝大多数日常开发中遇到的CORS问题,根据你的具体场景选择对应的配置方式即可,如果有特别复杂的场景,欢迎告诉我具体需求。

抱歉,评论功能暂时关闭!