V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wudaown
V2EX  ›  前端开发

React HTTP 请求问题

  •  1
     
  •   wudaown · 2022-01-10 21:14:06 +08:00 · 3235 次点击
    这是一个创建于 1078 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位大佬,

    目前在开发某项目,希望后端不能被外网访问

    前端和外网是通的,可以访问

    前端的机器和后端机器在同一个内网

    现在希望用户访问前端后由前端的机器发起请求而不是从用户网络发起请求。

    大佬们 这个能做到吗。。

    开发完了 今天测试才想起来网络请求是从用户网络出去的。。这我就很尴尬了。。

    59 条回复    2022-01-11 16:33:06 +08:00
    maplezzz
        1
    maplezzz  
       2022-01-10 21:16:40 +08:00
    部署前端的时候 nginx 做一下转发
    wudaown
        2
    wudaown  
    OP
       2022-01-10 21:17:57 +08:00
    @maplezzz 可以详细说一下吗?我 nginx 做法转发,然后后端就直接暴露了。。。
    ijse
        3
    ijse  
       2022-01-10 21:18:06 +08:00
    是不是弄个反代就好了? nginx proxy_pass
    wudaown
        4
    wudaown  
    OP
       2022-01-10 21:19:24 +08:00
    @maplezzz

    location /api/ {
    proxy_pass http://xx.xx.xx.xx (后端服务器地址
    }

    然后后端就直接可以通过 http://zz.zz.zz.zz/api (前端地址
    访问了。。。
    wudaown
        5
    wudaown  
    OP
       2022-01-10 21:19:58 +08:00
    @ijse 可以详细说一下吗?谢谢 我试过了 proxy_pass 后端直接暴露了
    wudaown
        6
    wudaown  
    OP
       2022-01-10 21:20:47 +08:00
    @maplezzz
    @ijse 澄清一下,这个 nginx 在前端服务器上面
    izoabr
        7
    izoabr  
       2022-01-10 21:24:03 +08:00
    不知道我的理解对不对哦。
    1 、你的 react 跟前端机器没关系,React 程序是运行在客户端浏览器里的。所以你说的前端是不是你那个提供 80 Http 服务的那个机器?我们暂且叫前置静态服务器吧。
    2 、如果这里说的后端是你的 API 服务的话,你不希望用户直接访问到,那就在刚才那个前置静态服务里,加一个反向代理,事实上大多数 React 项目都是这么运行的,前置一个 NGINX 提供静态服务和 API 的转发,这样在你后端服务器看访问来源是来自于这个 NGINX 的,但是这个请求体本身是用户端构造的,也就是说虽然不是直接访问,但这种代理访问形式也是不直接解决一些安全问题的。
    3 、所以你最好描述一下你的需求是什么,比如是安全需求,那首先考虑网络层面的安全,就应该把提供外网服务的前置服务器跟后端服务器分开,不要在一个子网里,然后两网之间加网络安全策略甚至是应用安全策略,比如就是允许前置服务器内网 IP 访问后端服务器的 80 端口,其它端口不允许;然后不允许后端服务器访问外网;但仅仅是网络安全策略还是不够的,因为毕竟用户构造的请求体可以直接被转发到后端,那就应该考虑进一步的应用安全策略了。
    wudaown
        8
    wudaown  
    OP
       2022-01-10 21:27:38 +08:00
    @izoabr
    1. 对的一个前置静态服务器存放 react 静态文件
    2. 可以有稍详细一点的配置 或者关键词 麻烦你了
    3. 安全的话,只要用户不能通过任何 url 直接访问后端 api 资源,其他安全问题团队其他人会处理。

    谢谢了
    wudaown
        9
    wudaown  
    OP
       2022-01-10 21:28:13 +08:00
    @izoabr
    补充一下
    1. 前置静态服务器就是用 nginx serve react 的文件
    izoabr
        10
    izoabr  
       2022-01-10 21:31:45 +08:00
    @wudaown #8

    那需求很简单明确了,就是不希望用户能通过 URL 访问到后端 API 资源对吧?
    解决方案也简单,拔网线就好了。 🐶

    NGINX 的转发就是 proxy_pass ,你就搜这个,或者搜 NGINX 反向代理。
    wudaown
        11
    wudaown  
    OP
       2022-01-10 21:33:08 +08:00
    @izoabr
    location /api/ {
    proxy_pass http://xx.xx.xx.xx (后端服务器地址
    }
    我试过了。。
    然后后端就直接可以通过 http://zz.zz.zz.zz/api (前端地址
    访问了

    是我哪里搞错了吗?
    izoabr
        12
    izoabr  
       2022-01-10 21:34:54 +08:00
    @wudaown #11 没错呀,这目的不就为了代理访问嘛?如果不想让它访问到,那就不配置这个就好了呀
    ch2
        13
    ch2  
       2022-01-10 21:36:56 +08:00
    @wudaown #11 zz.zz.zz.zz 是内网 ip ,外网压根访问不了
    izoabr
        14
    izoabr  
       2022-01-10 21:37:11 +08:00   ❤️ 2
    @wudaown #11 难道你希望用户没办法通过任何方法访问到后端?那不就约等于拔了网线了嘛?
    配置代理访问也不行,后端直接暴露给用户也不行,那不就完全不希望用户碰到后端的数据嘛?我不太理解了。。。
    wudaown
        15
    wudaown  
    OP
       2022-01-10 21:37:13 +08:00
    @wudaown 不配置的话,当我从浏览器发起请求的时候 ( http://xx.xx.xx.xx 这个地址是无法被外网访问的,资源就无法返回了。
    flyhaozi
        16
    flyhaozi  
       2022-01-10 21:37:13 +08:00
    我觉得你要的会不会其实是服务端渲染😅,不过也还是掩耳盗铃啊,就算不给 api ,页面数据也总有办法解析
    izoabr
        17
    izoabr  
       2022-01-10 21:40:50 +08:00
    外网 IP1<---->前置服务器<----->内网 IP1<------>内网 IP2<----->后端服务器

    你是不是想说,后端服务器,访问 http://内网 IP1/api/能访问到自己的服务?

    你不想它访问到是么?
    izoabr
        18
    izoabr  
       2022-01-10 21:42:15 +08:00
    @wudaown #15 对的呀,你看 11 楼的时候能访问,不行。现在不能访问也不行,那咋整啊
    wudaown
        19
    wudaown  
    OP
       2022-01-10 21:43:07 +08:00
    @izoabr 倒不如说是必须通过浏览器的 react 程序才可以访问,代理之后就可以直接通过 url 访问了
    wudaown
        20
    wudaown  
    OP
       2022-01-10 21:43:56 +08:00
    @izoabr
    xx.xx.xx 是内网地址
    zz.zz.zz.zz 是外网地址
    wudaown
        21
    wudaown  
    OP
       2022-01-10 21:44:45 +08:00
    #19 代理之后可以不同 react 程序 单纯从 url 访问了,这个不理想
    izoabr
        22
    izoabr  
       2022-01-10 21:46:02 +08:00
    @wudaown #19 哦,我明白你意思了。
    说白了就是不希望常规浏览器能随便访问到对吧?
    那就在你 react 里请求后端的时候做手脚,比如登录的时候分配一个 token ,然后你放到 axios 的 header 里,后端收到请求的时候先检查一下 token ,如果对,就正常返回,不对就直接跳 HTTP 500 或者 403
    wudaown
        23
    wudaown  
    OP
       2022-01-10 21:47:24 +08:00
    @izoabr 这个我已经做过了。。然而通过代理之后登录 API 是可以访问的,也就是说可以通过请求登录拿到 token
    izoabr
        24
    izoabr  
       2022-01-10 21:48:34 +08:00
    如果不想那么费劲,想通过简单一点的手段,就直接改一下 axios 的 User Agent ,在 NGINX 可以直接判断 User Agent ,发现不是你自定义的那个就直接 deny 掉
    wudaown
        25
    wudaown  
    OP
       2022-01-10 21:49:15 +08:00
    @izoabr 非常感谢,到现在我也很无解了,代码端各种验证登录自动退出登录,甚至频繁更新 token 我都做好了。。
    然后只要登录 api 能直接访问。。。就很难受
    wudaown
        26
    wudaown  
    OP
       2022-01-10 21:50:21 +08:00
    @izoabr #21 user-agent 可以通过正常访问手段窃取吧,打开开发者工具就能看到了
    izoabr
        27
    izoabr  
       2022-01-10 21:52:51 +08:00
    @wudaown #26 简单手段肯定破解也简单呗,要复杂甚至可以 RSA 加密,可以去搜下 axios 加密。
    我到目前为止还没有办法完全理解你的需求和问题。
    wudaown
        28
    wudaown  
    OP
       2022-01-10 21:53:51 +08:00
    我是不是可以通过监测 nginx 日志,在另外在前置服务器上面部署一个程序,去请求资源,然后返回前端。因为前端有 websocket 链接,所以检测程序可以主动发送信息
    wudaown
        29
    wudaown  
    OP
       2022-01-10 21:55:16 +08:00
    @izoabr #26 很难理解么?
    就是后端资源必须通过 react 程序访问。其他任何方式都不行
    oneisall8955
        30
    oneisall8955  
       2022-01-10 21:56:10 +08:00 via Android
    这个问题是不可避免的,refer + token 校验下吧
    rioshikelong121
        31
    rioshikelong121  
       2022-01-10 21:56:51 +08:00
    服务端渲染
    wudaown
        32
    wudaown  
    OP
       2022-01-10 21:57:24 +08:00
    @oneisall8955 一点办法都没有么。。refer + token 感觉还是很脆弱
    flyhaozi
        33
    flyhaozi  
       2022-01-10 21:57:41 +08:00
    @wudaown 在浏览器里发出去的请求不管怎样都是可以被各种工具伪造的
    wudaown
        34
    wudaown  
    OP
       2022-01-10 21:57:48 +08:00
    @rioshikelong121 可以多说两句么 谢谢
    oneisall8955
        35
    oneisall8955  
       2022-01-10 21:58:22 +08:00 via Android
    @izoabr 完全同意
    izoabr
        36
    izoabr  
       2022-01-10 21:59:10 +08:00
    @wudaown #28 那你就别走 HTTP 协议了,除了静态资源,React 运行起来之后就直接走 websocket 跟后端交互呗,或者连一个 MQ 消息服务器,请求啥直接发消息,然后等回复,这也挺好的一个方案,而且给未来后端的扩容留空间。
    rioshikelong121
        37
    rioshikelong121  
       2022-01-10 22:04:34 +08:00
    @rioshikelong121 你不就是怕后端接口被人偷么。。 改成服务端渲染,返回 html 给前端,不就增加了破解难度。当然人家爬你你是难以防住的。。
    wudaown
        38
    wudaown  
    OP
       2022-01-10 22:04:47 +08:00
    @izoabr 我一开始是这么做的,然而 websocket 地址还是暴露了。。好像确实无解。。
    flyhaozi
        39
    flyhaozi  
       2022-01-10 22:08:31 +08:00
    感觉每隔一段时间就能看到类似的贴子,之前的这些帖子里的讨论应该挺有帮助的,绝对的安全是不存在的,只能去找到一个平衡点
    https://www.v2ex.com/t/820478
    https://www.v2ex.com/t/806211
    https://www.v2ex.com/t/789385
    https://www.v2ex.com/t/638264
    izoabr
        40
    izoabr  
       2022-01-10 22:11:59 +08:00
    @wudaown #38 那肯定的,毕竟 React 运行在客户端,有心人肯定会有办法的。
    你看天眼查和淘宝什么的,他们为了防止扒数据,一个是服务端渲染,另一个是做用户行为检测,你去淘宝搜东西哪怕你已经登陆过了的实名用户,多翻几页一样跳出防爬虫验证。

    要么你就只能牺牲易用性,比如封装一个客户端,然后内部数据走个加密,但也不能完全保证万无一失。
    要么就是做用户层面的审核,反正方法也就是那么些,要么相信已注册用户,要么不全信,要么完全不信,完全不信你可以设置请求数据量,甚至可以按量收费。
    wudaown
        41
    wudaown  
    OP
       2022-01-10 22:16:36 +08:00
    我们怕的并不是用户,甚至这套东西没有任何数据。
    我们怕的是后端有漏洞,然后因为地址暴露在外网,被人直接把交易系统关掉
    wudaown
        42
    wudaown  
    OP
       2022-01-10 22:17:59 +08:00
    @izoabr #40 我去看看服务端渲染吧。


    @flyhaozi
    @rioshikelong121
    @izoabr 非常感谢各位的耐心解答
    izoabr
        43
    izoabr  
       2022-01-10 22:19:37 +08:00
    @wudaown #41 暴露在外面怕啥的,只要是实名用户,行为记录详细一点,不行就顺着网线找他去呗
    slmaaw
        44
    slmaaw  
       2022-01-10 23:30:28 +08:00 via Android
    ssr 可解 其实就是起个 node 中间层 用户访问中间层 中间层调用 api
    wudaown
        45
    wudaown  
    OP
       2022-01-10 23:51:34 +08:00
    @slmaaw ssr 刚才试过了,还是暴露了 api url
    wudaown
        46
    wudaown  
    OP
       2022-01-10 23:52:02 +08:00
    @slmaaw #44 或者说我少了中间层,如果可以的话 可以麻烦你详细说一下吗 谢谢
    crs0910
        47
    crs0910  
       2022-01-11 00:03:27 +08:00 via iPhone
    @wudaown 不要 ssr ,直接改成废掉 api 的方式,全部页面改用服务端渲染。
    这样等于重做。
    而且人家照样可以通过页面解析出数据。只不过只能拿到你页面用到的数据。
    假设你是因为 api 会暴露比你这个 react 应用用到的更多的数据,那你可以搞一个 node 后端程序包装一下你原来的 api ,只提供前端会用到的数据。
    crs0910
        48
    crs0910  
       2022-01-11 00:05:34 +08:00 via iPhone
    @wudaown 你可以说清楚为啥需要屏蔽别人访问 api ,那别人回答的时候就不用猜
    lyoe
        49
    lyoe  
       2022-01-11 03:17:03 +08:00
    LZ 是觉得接口容易被抓包吧。那就只有自定义通信协议了,可以看看闲鱼怎么做的。
    jguo
        50
    jguo  
       2022-01-11 09:06:57 +08:00
    感觉你要的是 api gateway
    xujiahui
        51
    xujiahui  
       2022-01-11 10:15:57 +08:00
    @wudaown #41 感觉这跟前端无关啊,怕后端有漏洞,这应该是后端和运维去关心的事呢,就算前后端都没问题,你只要有个主机 ip 地址,如果系统或用到的一些服务有漏洞别人一样能攻击,而且这种情况应该更多,现在应该很少通过找后端 url 请求的漏洞了吧
    jason94
        52
    jason94  
       2022-01-11 10:23:02 +08:00
    不管怎么搞,请求总是从客户端(浏览器)发起的,你想不直接暴露后端服务器,那肯定是在中间加一层。
    用 nginx 转发或者套个 CDN 可以解决。
    darknoll
        53
    darknoll  
       2022-01-11 10:29:11 +08:00
    访问后端接口不需要 token 啥的吗
    zhwithsweet
        54
    zhwithsweet  
       2022-01-11 11:18:58 +08:00
    这么说吧,做不到!
    只要能用浏览器访问,都是能伪造的。

    怎么可能又让前端访问,又不让前端访问呢??
    www5070504
        55
    www5070504  
       2022-01-11 11:36:03 +08:00
    你前端代码的执行是在用户浏览器上 不让外网访问 用户端怎么请求数据啊...
    fangcan
        56
    fangcan  
       2022-01-11 13:11:01 +08:00
    看了下没怎么明白? 可不可以后端服务器加白名单,只能 nginx 所在的服务器 ip 才有权限访问
    Longerrrr
        57
    Longerrrr  
       2022-01-11 13:24:33 +08:00
    把数据全放前端不就没后端了吗[doge]
    vipppppp
        58
    vipppppp  
       2022-01-11 15:58:03 +08:00
    除非服务器渲染,否则就是几层 nginx 的问题了。。。
    tagtag
        59
    tagtag  
       2022-01-11 16:33:06 +08:00   ❤️ 1
    react 不是 client ,浏览器才是,只要是浏览器能访问的,其他的 http client 一样可以访问,所以这个需求是不可能实现的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3061 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 13:12 · PVG 21:12 · LAX 05:12 · JFK 08:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.