搞定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检查的最佳实践和踩坑经验。希望对你有所帮助。如果你有更好的方案或建议,欢迎在评论区交流。这个技巧的拓展用法还有很多,后续我会继续分享这类博客。
