Cross-domain request handling
Basic Concepts of Cross-Origin Requests
Cross-origin requests refer to browser-imposed security restrictions that prevent scripts loaded from one origin from interacting with resources from another origin. The same-origin policy requires that the protocol, domain, and port must be identical to be considered same-origin. When any of these three elements differ, a cross-origin issue arises. For example:
http://a.com
requestinghttps://a.com
(different protocol)http://a.com
requestinghttp://b.com
(different domain)http://a.com:80
requestinghttp://a.com:8080
(different port)
Common Cross-Origin Solutions
JSONP
JSONP leverages the fact that <script>
tags are not restricted by the same-origin policy. It dynamically creates a script tag, passing a callback function name as a parameter to the server, which then returns data wrapped in a call to that function.
function handleResponse(data) {
console.log('Received data:', data);
}
const script = document.createElement('script');
script.src = 'http://example.com/api?callback=handleResponse';
document.body.appendChild(script);
CORS (Cross-Origin Resource Sharing)
CORS is a standard cross-origin solution supported by modern browsers. Servers declare which origins are allowed to access resources by setting response headers.
// Server-side configuration
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
Proxy Server
A same-origin backend server forwards requests to bypass the browser's same-origin policy.
// Frontend requests same-origin server
fetch('/api/proxy', {
method: 'POST',
body: JSON.stringify({
url: 'http://target-domain.com/api'
})
})
// Backend Node.js example
app.post('/api/proxy', async (req, res) => {
const { url } = req.body;
const response = await axios.get(url);
res.json(response.data);
});
Preflight Mechanism for Complex Requests
For HTTP methods that may have side effects on server data (e.g., PUT, DELETE), browsers first send an OPTIONS request for preflight.
// Preflight request example
fetch('http://api.example.com/data', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'value'
},
body: JSON.stringify({ key: 'value' })
});
Servers must properly handle OPTIONS requests:
app.options('/data', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'PUT');
res.header('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header');
res.sendStatus(204);
});
Credential Issues in Cross-Origin Requests
By default, cross-origin requests do not send credentials like cookies. Special settings are required:
// Frontend setting
fetch('http://api.example.com/data', {
credentials: 'include'
});
// Server-side setting
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Origin', 'http://your-domain.com'); // Cannot be *
WebSocket Cross-Origin Handling
The WebSocket protocol inherently supports cross-origin, but servers can decide whether to accept connections from specific origins.
const socket = new WebSocket('ws://example.com/socket');
// Server-side (Node.js + ws library)
const WebSocket = require('ws');
const wss = new WebSocket.Server({
verifyClient: (info, done) => {
const origin = info.origin;
if (origin === 'http://allowed-domain.com') {
done(true);
} else {
done(false, 401, 'Unauthorized');
}
}
});
Cross-Origin Image Resource Handling
Canvas operations on cross-origin images require special handling:
const img = new Image();
img.crossOrigin = 'Anonymous'; // Request CORS permission
img.onload = function() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// Now it's safe to manipulate the canvas
};
img.src = 'http://example.com/image.jpg';
Cross-Origin Font Loading
Web font files are also subject to same-origin policy restrictions. CORS headers must be set on the server:
@font-face {
font-family: 'MyFont';
src: url('http://example.com/font.woff') format('woff');
font-display: swap;
}
Server response must include:
Access-Control-Allow-Origin: *
Error Handling for Cross-Origin AJAX Requests
When cross-origin requests fail, browsers provide limited error information, so special attention is needed for error handling:
fetch('http://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error('Fetch error:', error);
// Note: Detailed error information is unavailable for cross-origin requests
});
Cross-Origin Solutions for Local Development
Common solutions during development:
-
Disable browser security policies (development only)
google-chrome --disable-web-security --user-data-dir=/tmp/chrome
-
Use development server proxy
// vite.config.js export default { server: { proxy: { '/api': { target: 'http://api.example.com', changeOrigin: true, rewrite: path => path.replace(/^\/api/, '') } } } }
Performance Optimization for Cross-Origin Requests
-
Preload CORS resources:
<link rel="preconnect" href="https://api.example.com"> <link rel="preload" href="https://api.example.com/data.json" as="fetch" crossorigin>
-
Combine requests to reduce preflight frequency
-
Cache CORS preflight results:
Access-Control-Max-Age: 86400
Cross-Origin Handling in Special Scenarios
postMessage for Cross-Document Communication
// Sender
const popup = window.open('http://other-domain.com');
popup.postMessage('Hello', 'http://other-domain.com');
// Receiver
window.addEventListener('message', event => {
if (event.origin !== 'http://your-domain.com') return;
console.log('Received message:', event.data);
});
Cross-Origin iframe Communication
// Parent page
document.getElementById('iframe').contentWindow.postMessage('Hello', 'http://child-domain.com');
// Inside iframe
window.parent.postMessage('Response', 'http://parent-domain.com');
Cross-Origin Restrictions for Browser Storage
- localStorage and IndexedDB follow same-origin policy
- Shared Workers can be used cross-origin with limitations
- Service Worker scope restrictions
// Explicitly define scope when registering Service Worker
navigator.serviceWorker.register('/sw.js', {
scope: '/app/' // Can only control requests under /app/
});
Cross-Origin Handling in Modern Frontend Frameworks
Proxy Setup in React
// setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://api.example.com',
changeOrigin: true,
})
);
};
Cross-Origin Configuration in Vue CLI
// vue.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://api.example.com',
ws: true,
changeOrigin: true
}
}
}
}
Security Considerations for Cross-Origin Requests
- Use
Access-Control-Allow-Origin: *
with caution - Validate the origin of all cross-origin requests
- Restrict allowed HTTP methods
- Implement CSRF protection for sensitive operations
// Example middleware to check Origin header
app.use((req, res, next) => {
const allowedOrigins = ['http://site1.com', 'http://site2.com'];
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.header('Access-Control-Allow-Origin', origin);
}
next();
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn