面试题答案
一键面试跨域产生原因
- 浏览器同源策略:同源策略是浏览器的一个安全功能,它限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这里的“源”由协议、域名和端口号组成,只有当这三者完全相同时,才属于同一个源。例如,
http://example.com:80
和https://example.com:80
由于协议不同,不是同源;http://example.com:80
和http://example.com:81
由于端口不同,也不是同源。当Angular应用(假设运行在http://localhost:4200
)向后端API(假设运行在http://api.example.com
)发起请求时,就会触发跨域问题,因为它们不属于同一个源。 - Angular应用本身:Angular应用在发送HTTP请求时遵循浏览器的同源策略。虽然Angular提供了强大的HTTP客户端模块(如
@angular/common/http
),但它本身并没有绕过同源策略的能力。如果没有适当的配置,直接向不同源的API发送请求就会遇到跨域限制。 - 静态服务器配置:如果静态服务器没有正确配置允许跨域请求,也会导致跨域问题。例如,常见的静态服务器如Nginx或Apache,默认情况下不会允许跨域请求。如果没有配置相应的跨域规则,浏览器会阻止从静态服务器加载的Angular应用向不同源的API发起请求。
解决方案及实现细节
- 前端层面(使用代理)
- 原理:在开发环境中,通过配置代理服务器,将所有跨域请求转发到后端API,这样对于浏览器来说,请求就变成了同域请求。
- 实现细节(以Angular CLI为例):
- 创建一个代理配置文件,例如
proxy.conf.json
。
{ "/api": { "target": "http://api.example.com", "secure": false, "changeOrigin": true } }
- 这里
/api
表示匹配以/api
开头的请求路径,target
是后端API的实际地址,secure
设置为false
表示允许通过HTTP协议转发请求,changeOrigin
设置为true
表示修改请求头中的Origin
字段,使其与目标服务器一致。 - 在
package.json
文件中,修改start
脚本:
{ "scripts": { "start": "ng serve --proxy-config proxy.conf.json" } }
- 这样在开发时运行
npm start
,Angular应用就会通过代理服务器向后端API发送请求,避免跨域问题。需要注意的是,此方法主要用于开发环境,生产环境需要在服务器端进行配置。
- 创建一个代理配置文件,例如
- 后端层面(设置CORS)
- 原理:后端服务器通过设置响应头来告诉浏览器允许哪些源的请求,从而绕过浏览器的同源策略限制。
- 实现细节(以Node.js + Express为例):
- 安装
cors
模块:npm install cors
。 - 在Express应用中引入并使用
cors
中间件:
const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()); // 其他路由和中间件配置 app.listen(3000, () => { console.log('Server running on port 3000'); });
- 上述代码中,
app.use(cors())
表示允许所有源的请求。如果需要更细粒度的控制,可以传入一个配置对象:
app.use(cors({ origin: 'http://localhost:4200', methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type'] }));
- 这里
origin
指定允许的源,methods
指定允许的HTTP方法,allowedHeaders
指定允许的请求头。
- 安装
- 服务器配置层面(以Nginx为例)
- 原理:在Nginx服务器配置中,添加允许跨域的响应头,从而让浏览器允许跨域请求。
- 实现细节:
- 编辑Nginx的配置文件(通常在
/etc/nginx/sites - available/
目录下),找到对应的服务器块(server
块)。
server { listen 80; server_name your_domain.com; location / { add_header 'Access - Control - Allow - Origin' '*'; add_header 'Access - Control - Allow - Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access - Control - Allow - Headers' 'DNT,X - User - Token,X - CSRF - Token,Keep - Alive,User - Agent,X - Requested - With,If - Modified - Since,Cache - Control,Content - Type,Content - Range,Range'; if ($request_method = 'OPTIONS') { return 204; } # 其他Nginx配置,如静态文件服务等 } }
add_header 'Access - Control - Allow - Origin' '*'
表示允许所有源的请求,如果需要限制,可以将*
替换为具体的源。add_header 'Access - Control - Allow - Methods'
和add_header 'Access - Control - Allow - Headers'
分别指定允许的HTTP方法和请求头。if ($request_method = 'OPTIONS')
块用于处理预检请求,直接返回204状态码表示允许跨域。修改完配置文件后,重启Nginx服务使配置生效:sudo systemctl restart nginx
。
- 编辑Nginx的配置文件(通常在