前言:
有这样一个需求,要求在第二个项目的页面中,嵌套展示第一个项目的前端页面,使用nginx作为中间件,此时直接去访问,就会出现跨域的问题
解决过程:
先附上最开始使用的nginx配置
#第二个项目,仅展示部分配置
server {
listen 8002;
server_name localhost;
location / {
root 这里是路径;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.1.1:7002/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#第一个项目,仅展示部分配置
server {
listen 8001;
server_name localhost;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
location / {
alias 这里是路径;
index login.html index.html;
}
location /xx/ {
proxy_pass http://192.168.1.1:7001/xx/;
}
}
在最初遇到这个问题的时候,作者也是查阅了很多资料,也使用过chatGPT去试图寻找答案,但是得到的结果都差强人意,在查找资料的过程中,找到最多的结果是
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,token';
使用了之后,跨域问题还是存在,于是找到了以下配置
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,token';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,token';
这段配置的大概功能是,如果请求方法为OPTIONS,它会返回204响应,以满足预检请求。如果请求方法不是OPTIONS,它会设置其他CORS相关的响应头。
注意:这项配置需要加在被访问的目标项目的nginx配置中,即本章配置中第一个项目的配置。通常情况下,只需要加到location /之后配置中即可
当时作者加到了第二个项目中的配置,也可以在一定程度上解决跨域问题,之后又出现了这个问题,于是纠正了一下自己的配置,以下是第二次纠正后的配置
#第二个项目,仅展示部分配置
server {
listen 8002;
server_name localhost;
location / {
root 这里是路径;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.1.1:7002/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#第一个项目,仅展示部分配置
server {
listen 8001;
server_name localhost;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,token';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,token';
alias 这里是路径;
index login.html index.html;
}
location /xx/ {
proxy_pass http://192.168.1.1:7001/xx/;
}
}
这样设置之后,理论上来说,跨域问题应该基本解决了才对,但是我分别试了192.168.1.1和127.0.0.1两个ip之后,还是会有跨域的情况出现,此时我又将每项配置梳理了一遍,发现问题似乎是由location /prod-api/内的配置引起的,因为这一段也设置了header,这里作者猜测与它有关,于是注释掉了这一段
location /prod-api/ {
#proxy_set_header Host $http_host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header REMOTE-HOST $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.1.1:7002/;
}
此时,跨域问题基本解决,第二个项目由于是二次开发的新项目,所以我选择了注释掉这段配置而不是删除,目前也没有出现其他问题,为什么说是基本解决呢,因为作者在测试的时候还有这样一个现象:使用edge浏览器,访问192.168.1.1没问题,但是访问127.0.0.1不能访问,会有跨域的情况,但是使用谷歌浏览器,访问两个ip都没有问题
时间有限,只能先做到这一步了不过现在的结果也够当前项目的使用了,之后有时间再琢磨这一块吧,这篇文章也是记录一下这件事
第一次补充
配置完成后还是有跨域分析,分析代码后发现后端Java代码内有全局跨域配置,但是不全,以下是允许所有来源的跨域请求的配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ... 其他安全配置 ...
// 配置CORS
.cors().and()
// ... 其他安全配置 ...
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com", "https://127.0.0.1:7001")); // 允许所有来源
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); // 允许的HTTP方法
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*")); // 允许所有标头
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
本文仅供参考,严禁全篇无脑转载,如有错误之处欢迎大佬指出