Nginx 跨域 + 无法设置 Cookie 解决办法
今天来分享一下关于项目部署上线时怎么解决跨域问题!!!
首先感谢一下大佬的方法,才让这个困扰我很久的问题得以解决!!!
这也是我请教大佬才解决的问题,大佬和我说,这是他耗费两周才解决的问题,我这也是属于前人栽树后人乘凉了,嘿嘿嘿!!!
前端问题
前端没有携带 cookie 导致后端识别不到
1) 前端 axios 是否开启了 withCredentials=true
2) 在 OpenAPI 的那边配置项,设置下 withCrendential
首先 F12 看 login 接口对应的网络请求有没有 ⚠️,如果有那是后端的问题,如果没有那是前端的问题
后端问题
YML 配置
复制代码
server:
servlet:
session:
cookie:
domain: 域名或者IP
http 环境就不要使用 secure 和samesite
使用宝塔跨域
后端相关的反向代理+跨域
server {
# 这个监听的端口任意都行,但是要注意前端要请求这个端口
listen 9090;
server_name localhost;
location / {
# 禁止非 GET|POST|HEAD|OPTIONS|PUT|PATCH|DELET 的请求
if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) {
return 444;
}
set $origin $http_origin;
# 重点!比如:
# $origin !~ '^http?://leikooo\.com$
# $origin !~ '^http?://127.0.0.1$
if ($origin !~ '^http?://服务器IP或者域名$') {
set $origin 'http://服务器IP或者域名';
}
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$origin" always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain charset=UTF-8';
add_header Content-Length 0;
return 204;
}
if ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') {
add_header Access-Control-Allow-Origin "$origin" always;
add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always;
add_header Access-Control-Allow-Credentials true always;
}
# 反向代理到后端具体运行的端口
proxy_pass http://localhost:后端实际运行端口;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意:
-
前端请求 9090 (上面 server 模块下 listen 的端口)而不是直接请求后端实际运行端口
-
直接请求后端端口,那么 Nginx 就失去了存在的意义!
-
宝塔 + 服务器放行 9090 端口,这个要注意!!(具体看自己写的是哪个端口)
-
完成 添加 nginx 配置 + 放行端口 正常就没什么问题了!
使用原生 Nginx 跨域
经过实际测试,用 nginx 跨域就可以解决
user root;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
sendfile on;
keepalive_timeout 65;
#gzip on;
# 前端配置不是重点
server {
listen 80;
server_name localhost ;
root /root/app/dist;
# 访问默写前端页面 404 就是没加下面这行的原因
try_files $uri $uri/ /index.html;
location / {
index index.html index.htm;
}
}
# 后端相关的反向代理+跨域
server {
# 这个监听的端口任意都行,但是要注意前端要请求这个端口
listen 9090;
server_name localhost;
location / {
# 禁止非 GET|POST|HEAD|OPTIONS|PUT|PATCH|DELET 的请求
if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) {
return 444;
}
set $origin $http_origin;
# 重点!比如:
# $origin !~ '^http?://leikooo\.com$
# $origin !~ '^http?://127.0.0.1$
if ($origin !~ '^http?://服务器IP或者域名$') {
set $origin 'http://服务器IP或者域名';
}
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$origin" always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain charset=UTF-8';
add_header Content-Length 0;
return 204;
}
if ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') {
add_header Access-Control-Allow-Origin "$origin" always;
add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always;
add_header Access-Control-Allow-Credentials true always;
}
# 反向代理到后端具体运行的端口
proxy_pass http://localhost:后端实际运行端口;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
注意:
1)前端请求 9090
而不是直接请求后端实际运行端口
2)服务器放行 9090
端口,这个要注意!!(具体看自己写的是哪个端口)
使用 HTTPS
实际测试使用域名 + HTTPS 也可以解决
这里看一下大佬写的!!!
教程:https://www.code-nav.cn/post/1831983737277050881
BUG
- 前端使用域名,但是前端后端使用 ip ,导致 session 设置不上
解决:前后端统一,要用域名都用域名、IP 都用 IP
- 还是不行?
1)端口是否放行!!!
2)前端请求的端口是否是 Nginx listen 的端口,不要直接请求实际端口 !!!