通过nginx配置解决前端跨域问题

一、什么是跨域

1. 同源策略

同源策略是浏览器中的一种安全机制,用于阻止恶意代码窃取数据或者执行一些危险操作,简单来说就是同协议,同域名,同端口,三者缺一不可。

2.跨域的情景

跨域指的是在浏览器发送请求时,请求的服务器URL与当前页面的域名不一致,即不满足同源策略。比如:

前端网址:http://localhost:8000。
服务器URL:http://localhost:8001。

当该端口的网站8000尝试访问服务器端接口时,由于端口不通,就会触发跨域。

3.跨域的原因

跨域问题主要是由浏览器中的安全机制:同源策略(same-origin policy) 引起的,这是浏览器为了用户安全而设计的一个重要机制。能够阻止恶意网站通过JavaScript访问另一个域的敏感数据或执行潜在的恶意操作。

因此当服务器请求和当前域名不同源时,浏览器会拦截客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

4.浏览器原理

每当发起访问时,浏览器在背后都会校验前端应用和服务端是否同源,源是由一系列属性构成的,包括网络传输协议,主机名称,端口等等。比如,
https://www.facebook-clone.com的传输协议是https,主机名称是www.facebook-clone.com
,端口是443(这里被隐藏了,https协议的默认访问端口是443)。

为了验证同源,浏览器会在所有请求中附带一个特殊的请求一起发送给域信息接收服务器。比如有个应用运行在域localhost:3000上,这个特殊请求的格式将像下面这样:

Origin: http://localhost:3000

作为回应,服务器返回的response会附带一个包含键为 Access-Control-Allow-Origin 的 header,用来标示什么样的源可以访问服务器的资源。该键可以对应两种值:

第一种,严格模式,只有一个指定的源可以获得权限访问:

Access-Control-Allow-Origin: http://localhost:3000

第二种,宽松模式,服务端允许任何源访问自己的资源:

Access-Control-Allow-Origin: *

浏览器接收到该响应后,会把前端应用的域和服务器返回的Access-Control-Allow-Origin值比较,如果比较不匹配,那么此次访问就被报错了,并且会返回一个CORS错误的提示。

二、跨域的解决方案

解决跨域问题有多种方法,如JSONP、CORS、Nginx代理等。

1.前后端结合(JsonP)

虽然jsonp也可以实现跨域,但是因为jsonp不支持post请求,应用场景受到很大限制,所以不考虑。

2.后端配置(跨域资源共享(CORS))

跨域资源共享即开放跨域请求,CORS 是w3c标准的方式,服务器默认是不被允许跨域的,可以通过给Nginx服务器配置Access-Control-Allow-Origin *,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。

在实际的浏览器发送请求中,如果浏览器检测到跨域,它会尝试发起一次请求,然后查看返回的内容中,是否一个有允许跨域请求的标记(CORS响应头),如果有正确的标记,那么就不拦截;如果没有标记,浏览器就会阻止这个请求,并报错。

同源策略只存在浏览器端,通过服务器转发请求可以达到跨域请求的目的,但是会增加服务器的负担,且访问速度慢。

3.Nginx配置代理请求的CORS

通过Nginx代理可以将跨域变成同源。首先要明白,是谁把前台向后台的请求拦截下来的?不是后台,而是浏览器。如果要避免跨域,只要让浏览器认为“我正在向同一个域发起请求”,就可以了。

在前端的代码中,可以在服务器的请求URL前加个特殊前缀,比如加一个/api/作为前缀,然后再nginx的配置中识别到/api/这个前缀就转发到服务器实际的地址中。

server {
    listen       80;
    server_name  localhost;

    location /api/ {
        proxy_pass   http://localhost:8001/;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;

        try_files $uri $uri/ /index.html;
        expires 60s;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
         root   /usr/share/nginx/html; 
     }
}

一般情况下浏览器访问时是只显示客户端的访问地址,而服务器nginx转发到哪个地址我们是看不到的,这样就很难判断nginx代理是否生效。我们可以在nginx的配置文件上加上以下配置:

add_header backendIP $upstream_addr;

配置更新了之后,需要再重启一下Nginx服务。

nginx -s reload

如果不想加特殊前缀,也有其他的方式可以解决

3.1.history模式

history 模式会有一个问题,就是当页面刷新时,如果没有合适的配置,会出现页面 404 的错误,因此需要额外的配置。

try_files

try_files 解决的是:当 nginx 找不到客户端需要的资源时该怎么办的问题。对于找不到的 url,需要将首页 html 返回, nginx 配置如下:

location  / {
      try_files $uri $uri/ /index.html;
}

这样虽然解决了页面刷新404的问题,但是如果用post调用后端接口服务,会出现405 not allowed。这是因为 Nginx 会将匹配不上的url 匹配到首页html,但是html是静态资源,Nginx服务器默认post不能访问静态资源,所以会出现 405 not allowed。

error_page
error_page可以将所有POST 405错误发送到命名位置@405 , 配置如下:

location / {
    root   /usr/share/nginx/html;
    try_files $uri $uri/ /index.html;
    index  index.html index.htm;
    error_page 405 =200 @405;  #405页面处理
}

location @405 {         
     proxy_set_header Host $host; 
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_pass http://ip:端口$request_uri ;
}   

配置了之后接口访问正常

3.2 hash模式

hash不论页面的路由路径是什么,实际网络请求的都是主域名或IP:Port,所以并不会出现404问题。所以Nginx 配置并不需要加 try_files,但是路由找不到请求路径的文件,会出现404,所以需要配置 error_page。

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    error_page 404 =200 @404;  #404页面处理
}

location @404 {         
     proxy_set_header Host $host; 
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_pass http://ip:端口$request_uri ;
 }   

三、可能会出现的问题

1.Nginx报错405 Method Not Allowed

Request URL: http://localhost:8001/api/getinfo
Request Method: POST
Status Code: 405 Not Allowed
Remote Address: localhost:8001
Referrer Policy: strict-origin-when-cross-origin

前置情况:前端解决跨域问题、路由history模式

出现这个原因:正常情况下,接口地址可以直接设置后端接口地址,但是这样会引起浏览器跨域,如果后端没有设置接口允许跨域,那么就需要前端在nginx做一层转发。为了解决浏览器跨域问题,接口地址直接设置的业务系统访问地址,这接口就相当于去请求 /api/getinfo 这个路径下的文件,由于静态资源的,都不允许静态文件响应POST请求,只能通过get方法访问,所以这里就报错405。

解决方法:加前缀转发,或者配置配置405状态转发。

2. Nginx报错404 Not Found

前置情况:前端解决跨域问题、路由hash模式

出现这个原因:跟上面出现的情况一样,都是因为nginx配置问题,也是Nginx把接口请求当做访问静态资源,找不到文件就报错404。
解决方法:加前缀转发,或者配置配置404状态转发。

3. Nginx报错502 Bad Gateway

页面报错显示502 Bad Gateway,查看后端nginx发现并无前端的请求,并且后端服务没有问题。使用proxy_pass 中填写的地址用postman模拟是可以正常访问。

问题的原因是在于 nginx中传递了host,而后端也是nginx反向代理,而此nginx中并无原始请求的host,故报502错误。把Host的设置删掉即可。

proxy_set_header Host $host;

4. 接口返回HTML

这是因为nginx配置导致的

server {
     listen       80
     server_name  localhost;
     location / {
         root   html;
         index  index.html index.htm;
     }
     # To allow POST on static pages 允许静态页使用POST方法
     error_page  405     =200 $uri;
}

error_page 405 =200 $uri; 是将POST请求转换为GET。而使用此方法会出现返回不一致的问题,如这里应返回json文本,此处却是 html的文本,其原因就是因为请求的方式不一致,因返回格式不一致,导致前端报错。

在这里插入图片描述

<think>好的,我现在需要帮助用户解决前后端分离部署到云服务器后前端出现404错误的问题。首先,我得回忆一下前后端分离部署的基本原理,可能的问题点在哪里。根据用户提到的引用内容,他们提到了几种部署方式,比如前端静态资源用Nginx代理,后端用jar或war包,同时需要Nginx解决问题。 用户的问题前端访问报404,这意味着资源未找到。可能的原因有很多,我需要逐步分析。首先,前端资源是否正确部署到了服务器指定的路径下?比如,前端的dist目录是否放到了Nginx配置的root或alias指向的位置。如果路径不对,Nginx无法找到文件,就会返回404。 其次,Nginx配置是否正确。用户可能配置了反向代理,但路径转发是否有问题。例如,前端路由如果是history模式,可能需要配置try_files来重定向到index.html,否则在直接访问子路由时,Nginx会尝试查找对应的文件,导致404。 另外,后端服务的反向代理配置是否正确。如果后端的API路径没有被正确代理到后端服务,也可能导致前端请求API时出现404,但用户的问题似乎明确是前端访问的问题,所以可能更关注静态资源的问题。 还需要检查云服务器的安全组设置,是否开放了前端使用的端口,比如80或443,确保外部可以访问到Nginx服务。此外,文件权限问题也可能导致Nginx无法读取静态文件,需要检查dist目录及其文件的权限是否正确。 还有可能是前端构建时的问题,比如构建生成的路径不对,比如使用了绝对路径而服务器上路径不一致,或者baseUrl配置不正确,导致引用的资源路径错误,从而404。 总结下来,可能的排查步骤包括:检查Nginx配置中的静态资源路径是否正确;确认前端文件是否成功上传到服务器对应路径;检查Nginx的路由配置是否处理了前端路由的history模式;验证后端API代理配置是否正确;检查服务器端口和文件权限;确认前端构建配置是否正确。 可能需要用户提供Nginx配置片段来进一步诊断,但根据常见问题,给出通用的解决步骤。比如,确保Nginx的root指向正确,使用try_files处理路由,检查后端代理配置,确认静态文件存在且权限正确,以及查看Nginx的error日志获取更详细的错误信息。</think>### 前后端分离部署前端404错误解决方案 #### 1. 验证静态资源部署路径 - **检查Nginx配置**:确保`nginx.conf`中的`root`或`alias`指向前端静态资源目录(如`/var/www/dist`),并确认文件已上传至该路径。 ```nginx server { listen 80; server_name example.com; location / { root /var/www/dist; # 检查路径是否正确 index index.html; } } ``` - **文件权限问题**:通过命令`ls -l /var/www/dist`确认文件权限,若权限不足,执行`chmod -R 755 /var/www/dist`。 #### 2. 处理前端路由模式 - **History模式适配**:若前端使用Vue Router的`history`模式,需在Nginx中添加`try_files`配置,避免直接访问子路由时404: ```nginx location / { try_files $uri $uri/ /index.html; # 关键配置 } ``` #### 3. 检查反向代理配置 - **后端API代理**:确认Nginx中后端接口的代理配置是否正确指向后端服务(如端口号、路径匹配规则): ```nginx location /api/ { proxy_pass http://localhost:8080; # 确保端口与后端服务一致 proxy_set_header Host $host; } ``` #### 4. 验证网络与端口 - **云服务器安全组**:检查云服务器的防火墙规则是否开放了前端服务的端口(如80/443)。 - **Nginx服务状态**:通过`systemctl status nginx`确认Nginx正常运行,若有错误日志可通过`tail -f /var/log/nginx/error.log`排查。 #### 5. 前端构建配置检查 - **publicPath设置**:若前端项目配置了`publicPath`(如Vue的`vue.config.js`),需与Nginx中的路径层级保持一致: ```javascript module.exports = { publicPath: '/', // 需与Nginx配置的子路径匹配(如部署在子目录需设为'/subdir/') } ``` #### 6. 其他可能性 - **缓存问题**:清除浏览器缓存或使用无痕模式测试。 - **文件完整性**:重新上传前端构建产物(`dist`目录),避免传输过程中文件损坏。 --- ### 相关问题 1. 如何通过Nginx日志快速定位404错误原因? 2. 前后端分离项目中如何配置HTTPS证书? 3. 使用Docker部署时如何优化镜像体积?[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值