跨域 
1. 什么是跨域?为什么会有跨域限制? 
答案:跨域是指在浏览器中,当前页面的脚本试图访问不同源(协议、域名、端口三者有任一不同)的资源时受到的限制。
跨域限制的主要原因是安全考虑,它是浏览器的同源策略的一部分,用于防止恶意脚本访问其他网站的敏感数据。
2. 常见的跨域解决方案有哪些? 
答案:常见的跨域解决方案包括:
- CORS(跨域资源共享)
- JSONP
- 代理服务器
- postMessage
- WebSocket
- document.domain + iframe
- 浏览器插件(如Chrome的Allow-Control-Allow-Origin)
3. 什么是CORS?如何实现CORS? 
答案:CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种基于HTTP头的机制,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
实现CORS的步骤:
- 服务器端设置响应头: - Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
 
- 对于非简单请求,服务器需要处理OPTIONS预检请求
- 客户端无需特殊设置,使用普通AJAX即可
示例(Node.js + Express):
javascript
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});4. JSONP的原理是什么?如何实现JSONP? 
答案:JSONP(JSON with Padding)利用了<script>标签不受同源策略限制的特性。它通过动态创建script标签,向服务器请求数据,服务器返回一个函数调用,这个函数调用的参数就是我们需要的数据。
实现JSONP的步骤:
- 客户端定义一个回调函数
- 创建<script>标签,src指向接口地址,并带上回调函数名
- 服务器接收到请求后,将数据作为参数和函数名拼接成函数调用的形式返回
示例:
javascript
// 客户端
function handleResponse(data) {
    console.log(data);
}
const script = document.createElement('script');
script.src = 'http://example.com/api?callback=handleResponse';
document.body.appendChild(script);
// 服务器端(Node.js)
app.get('/api', (req, res) => {
    const data = {name: 'John', age: 30};
    const callback = req.query.callback;
    res.send(`${callback}(${JSON.stringify(data)})`);
});5. 什么是预检请求(Preflight Request)?什么情况下会触发预检请求? 
答案:预检请求是在某些跨域请求前,浏览器自动发起的 OPTIONS 请求,用于检查实际请求是否可以安全地发送。
触发预检请求的情况:
- 使用了以下HTTP方法之一:PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH
- 人为设置了以下集合之外首部字段:Accept、Accept-Language、Content-Language、Content-Type
- Content-Type 的值不属于以下之一:application/x-www-form-urlencoded、multipart/form-data、text/plain
6. 如何使用postMessage实现跨域通信? 
答案:postMessage是HTML5引入的API,可以安全地实现跨源通信。
使用步骤:
- 在发送方使用 targetWindow.postMessage(message, targetOrigin)发送消息
- 在接收方使用 window.addEventListener('message', handler)监听消息
示例:
javascript
// 发送方(http://example.com)
const iframe = document.getElementById('myIframe');
iframe.contentWindow.postMessage('Hello from example.com', 'http://target.com');
// 接收方(http://target.com)
window.addEventListener('message', (event) => {
    if (event.origin !== 'http://example.com') return;
    console.log('Received message:', event.data);
});7. 什么是CORS预检请求?如何优化CORS预检请求? 
答案:CORS预检请求是一种OPTION请求,用于检查实际请求是否可以安全地发送。
优化CORS预检请求的方法:
- 使用Access-Control-Max-Age头部缓存预检请求结果
- 减少非简单请求:尽可能使用简单请求(GET、POST、HEAD)
- 合并多个请求以减少预检请求的次数
- 在服务器端正确处理OPTIONS请求
示例(设置预检请求缓存时间):
javascript
res.header('Access-Control-Max-Age', '86400'); // 缓存预检请求结果24小时8. 如何在Node.js中实现CORS中间件? 
答案:在Node.js中,可以使用Express框架并实现一个CORS中间件:
javascript
function corsMiddleware(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
  // 处理 OPTIONS 请求
  if ('OPTIONS' === req.method) {
    res.sendStatus(200);
  } else {
    next();
  }
}
app.use(corsMiddleware);9. 跨域资源共享(CORS)的安全隐患有哪些?如何防范? 
答案:CORS的安全隐患主要包括:
- 过于宽松的Access-Control-Allow-Origin设置
- 错误的凭证处理
- 不安全的响应暴露
防范措施:
- 严格限制Access-Control-Allow-Origin,避免使用通配符 *
- 谨慎处理Access-Control-Allow-Credentials
- 使用Access-Control-Expose-Headers限制暴露的响应头
- 正确配置Access-Control-Allow-Methods和Access-Control-Allow-Headers
- 实施内容安全策略(CSP)
10. 什么是子域名跨域?如何解决子域名跨域问题? 
答案:子域名跨域是指在同一主域名下的不同子域名之间的跨域问题,例如 sub1.example.com 和 sub2.example.com 之间的通信。
解决方法:
- 使用document.domain:javascriptdocument.domain = 'example.com';
- 使用postMessage
- 使用CORS
- 使用代理服务器
- 使用 jsonp
- 使用 window.name
注意:document.domain方法只适用于二级域名相同的情况,且存在安全风险,应谨慎使用。