V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
seeyourface
V2EX  ›  NGINX

请教大佬们一个反向代理问题

  •  
  •   seeyourface · 2023-08-25 10:02:35 +08:00 · 2118 次点击
    这是一个创建于 450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前提: A 应用中通过微前端的方式嵌入了一个 B 应用,A 应用运行在 nginx 监听的 443 端口,防火墙开放 443 端口。 B 应用运行在 8081 端口并且防火墙不开放该端口,B 应用拦截器中做了一个简单的认证,只要请求 B 应用的接口中的请求头含有 X-User-Name 头部并且值不为空就能请求成功,否则认证失败。 现在在 nginx 中将/source (表示 B 应用接口的请求)开头的请求都代理到了 8081 ,且同时自动添加请求头部 X-User-Name ,本意是使 A 应用能正常访问 B 应用 但是浏览器访问 Protocol://ip:6433/source 时 B 应用会自动跳转到自己的/home 地址,然后请求主页相关接口并且都带上了头部,导致可以从浏览器访问 B 应用。 在不修改代码的情况下,能不能只通过修改 nginx 配置实现浏览器无法访问 B 应用,A 应用通过嵌入方式可以正常访问 B 应用;

    nginx 反向代理配置:

    location ^~ /source { proxy_set_header X-User-Name '1'; proxy_pass https://127.0.0.1:8081; }

    14 条回复    2023-08-25 13:49:33 +08:00
    luhuisicnu
        1
    luhuisicnu  
       2023-08-25 10:14:07 +08:00
    简单,浏览器无法主动添加这个 X-User-Name header 。所以 nginx 配置里面不加这个 header ,让 A 应用嵌入的 B 应用的超链接,js 添加这个 header ,就行了
    dier
        2
    dier  
       2023-08-25 10:19:33 +08:00
    ChatGPT 建议加一个"add_header X-Frame-Options "SAMEORIGIN";" 来限制非同源来访问这个页面。你试试

    ```
    location ^~ /source {
    proxy_set_header X-User-Name '1';
    proxy_pass https://127.0.0.1:8081;
    add_header X-Frame-Options "SAMEORIGIN"; # 添加 X-Frame-Options 防止页面被嵌套
    }

    ```
    seeyourface
        3
    seeyourface  
    OP
       2023-08-25 10:25:30 +08:00
    @luhuisicnu 我懂前端,前端开发说微前端的嵌入方式他只是引入了一个 B 应用的地址,具体请求的接口他都不知道也不能往请求头里面加 header ,大佬你这个 js 添加 header 是指什么
    seeyourface
        4
    seeyourface  
    OP
       2023-08-25 10:26:01 +08:00
    @seeyourface 说错了,我不懂。。。
    seeyourface
        5
    seeyourface  
    OP
       2023-08-25 10:28:39 +08:00
    @dier 试了一下,还是不行
    dier
        6
    dier  
       2023-08-25 10:37:56 +08:00
    @seeyourface #5 试试这个呢 "add_header Content-Security-Policy "frame-ancestors 'self'";"
    zhongerbing
        7
    zhongerbing  
       2023-08-25 10:41:34 +08:00
    @seeyourface #3 微前端一般都有通信方式,直接使用通信的方式来让 b 应用添加。如果单独打开也拿不到 a 通信过来的数据,应该就可以实现你的需求
    cdswyda
        8
    cdswyda  
       2023-08-25 10:54:40 +08:00
    allow 127.0.0.1; # 只让 nginx 代理访问
    deny all; # 禁止其他所有 IP 地址访问
    JohnSwit
        9
    JohnSwit  
       2023-08-25 11:04:45 +08:00
    要实现这个需求,其实就是确保访问 B 的时候,根据条件带上 X-User-Name Header ,你这样设置跳转肯定会自动带上的。

    你的 B 应用是内嵌到 A 应用内部,本意是使 A 应用能正常访问 B 应用,那么从 A 应用请求到 B 应用,应该是可以带上 A 应用的标识吧?

    基于你的条件,location ^~ /source { proxy_set_header X-User-Name '1'; proxy_pass https://127.0.0.1:8081; }

    你可以添加多一个 IF 条件去判断,包含 A 应用的特定标识再去添加头:
    if ($http_referer ~* "yourAAppIdentifierHere") {
    proxy_set_header X-User-Name '1';
    }
    dallaslu
        10
    dallaslu  
       2023-08-25 11:10:13 +08:00
    这问题与反代、AB 应用关系都不大吧,问题的核心是,如何让微前端可用,而浏览器直接访问不可用。

    重点是你这个「微前端」嵌入是怎么实现的。(啥叫微前端嵌入啊?)

    按描述来说,既不关心接口,又不能修改请求头,所以……是 iframe 吗?

    Nginx 可以尝试检查 referer ,或者在页面写入一段 JS ,用来检查是否处于「被嵌入」状态,否则跳转页面。
    seeyourface
        11
    seeyourface  
    OP
       2023-08-25 11:14:58 +08:00
    @dallaslu 前端只给我发了一这行代码,他说嵌入 B 应用只写了一行:<micro-app name="B" url={micro_url} baseroute="/preparation/B" keep-alive />
    seeyourface
        12
    seeyourface  
    OP
       2023-08-25 11:16:18 +08:00
    @cdswyda 这样嵌入的应用也访问不了
    dallaslu
        13
    dallaslu  
       2023-08-25 11:22:55 +08:00
    根据文档 <https://zeroing.jd.com/micro-app/docs.html#/zh-cn/env>,可以检测到是否为微前端。插入脚本检测环境即可。

    ```nginx
    server {
    listen 80;
    server_name your_domain.com;

    location /source {
    proxy_pass http://backend_server;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    sub_filter '<head>' '<head><script>if(!window.__MICRO_APP_ENVIRONMENT__) alert('You bad bad')</script>';
    sub_filter_once on;
    }
    }
    ```
    seeyourface
        14
    seeyourface  
    OP
       2023-08-25 13:49:33 +08:00
    @dallaslu 确实可以从请求头的 Referer 字段入手,微前端访问和浏览器访问这个字段的内容不同,多谢大佬
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2545 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:35 · PVG 23:35 · LAX 07:35 · JFK 10:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.