搞定Origin检查那些坑 真实项目中的实践经验分享

瑞云的笔记 安全 阅读 588
赞 66 收藏
二维码
手机扫码查看
反馈

我的写法,亲测靠谱

在前端开发中,Origin检查是个非常重要的安全措施,尤其是当你需要处理跨域请求时。我一般这样处理:

搞定Origin检查那些坑 真实项目中的实践经验分享

首先,在服务器端设置CORS(跨源资源共享)策略,确保只有指定的Origin可以访问你的API。这里是一个简单的Node.js示例:

const express = require('express');
const app = express();

const allowedOrigins = ['https://example.com', 'https://another-example.com'];

app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

app.get('/api/data', (req, res) => {
  res.json({ message: 'This is a protected resource' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

这段代码中,我们通过res.setHeader('Access-Control-Allow-Origin', origin)来设置允许的Origin。这样做的好处是,只有在allowedOrigins数组中的Origin才能访问我们的API,从而避免了不必要的跨域请求。

在客户端,我们可以通过一些简单的JavaScript来检查响应头,确保请求是从正确的Origin发出的。这里是一个简单的示例:

fetch('https://jztheme.com/api/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error('There was a problem with the fetch operation:', error);
  });

在这个示例中,我们使用fetch来发起请求,并通过response.ok来检查响应是否成功。如果响应失败,我们抛出一个错误并捕获它。

这几种错误写法,别再踩坑了

在实际项目中,我见过不少关于Origin检查的错误写法,这里分享几个常见的坑,希望你不要再踩进去。

1. **不设置CORS策略**:最常见也是最致命的错误就是完全忽略CORS策略。如果你不设置CORS策略,默认情况下浏览器会阻止所有跨域请求。这种情况下,你的API将无法被其他域访问。

// 错误示例
app.get('/api/data', (req, res) => {
  res.json({ message: 'This is an unprotected resource' });
});

2. **允许所有Origin**:有些人为了省事,直接允许所有Origin访问API。这种做法非常危险,因为它相当于把你的API暴露给了所有人。

// 错误示例
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

3. **忽略预检请求**:在CORS中,有些请求会被浏览器自动发送预检请求(OPTIONS请求)。如果你忽略了这些请求,可能会导致一些问题。例如,浏览器可能会阻止某些请求,因为它们没有通过预检。

// 错误示例
app.get('/api/data', (req, res) => {
  res.json({ message: 'This is a protected resource' });
});

正确的做法是处理这些预检请求:

// 正确示例
app.options('/api/data', (req, res) => {
  res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.status(204).send('');
});

app.get('/api/data', (req, res) => {
  res.json({ message: 'This is a protected resource' });
});

实际项目中的坑

在实际项目中,我还遇到过一些比较隐蔽的坑,这里分享一下我的经验。

1. **动态Origin**:有时候,你需要根据用户的登录状态或其他条件动态设置允许的Origin。这种情况下,你需要在服务器端做一些额外的处理。例如,你可以从数据库中读取允许的Origin列表,然后动态设置。

const allowedOrigins = ['https://example.com', 'https://another-example.com'];

app.use(async (req, res, next) => {
  const user = await getUserFromRequest(req); // 假设你有一个函数可以从请求中获取用户信息
  const allowedOriginsForUser = await getAllowedOriginsForUser(user); // 根据用户获取允许的Origin

  const origin = req.headers.origin;
  if (allowedOriginsForUser.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

2. **多重域名**:有时候,你的应用可能有多个域名,每个域名都需要单独设置CORS策略。这种情况下,你需要在服务器端为每个域名设置不同的CORS策略。例如:

const corsOptions = {
  'https://example.com': {
    origin: 'https://example.com',
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization']
  },
  'https://another-example.com': {
    origin: 'https://another-example.com',
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization']
  }
};

app.use((req, res, next) => {
  const origin = req.headers.origin;
  const options = corsOptions[origin];
  if (options) {
    res.setHeader('Access-Control-Allow-Origin', options.origin);
    res.header('Access-Control-Allow-Methods', options.methods.join(', '));
    res.header('Access-Control-Allow-Headers', options.allowedHeaders.join(', '));
  }
  next();
});

3. **缓存问题**:有时候,浏览器会缓存CORS预检请求的结果,导致你在修改了CORS策略后仍然无法生效。这种情况下,你可以通过设置Cache-Control头来解决这个问题:

app.options('/api/data', (req, res) => {
  res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
  res.status(204).send('');
});

通过设置Cache-Control头,可以确保每次请求都重新验证CORS策略。

总结

以上是我总结的一些关于Origin检查的最佳实践和踩坑经验。希望对你有所帮助。如果你有更好的方案或建议,欢迎在评论区交流。这个技巧的拓展用法还有很多,后续我会继续分享这类博客。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论
♫柚溪
♫柚溪 Lv1
读完这篇文章,我对技术的价值有了新的认识,不再只关注技术的难度。
点赞 3
2026-02-06 11:25