• 利用nginx内部访问特性实现静态资源授权访问


    在nginx中,将静态资源设为internal;然后将前端的静态资源地址改为指向后端,在后端的响应头部中写上静态资源地址。

    近期客户对我们项目做安全性测评,暴露出一些安全性问题,其中一个是有些静态页面(*.html)无须授权即可直接访问,里面的信息一览无遗,不安全。这些静态页面都是arcgis地图页面,依赖arcgis for js,没有办法做成一般意义上的动态页面。或者说,该项目是个老项目,目前只处于维护阶段,大规模改头换面不现实。

    怎么办,有没有什么方法,不改这些静态页面,或者是不做大的调整,就能实现只有登录后才能访问它们呢?看到网上有文章介绍,可以利用nginx的internal特性,将静态资源设为内部访问,即可实现需要鉴权才能访问。

    原理说起来也比较简单。所谓内部访问,是指你直接在浏览器输入静态资源地址,将无法访问,会直接报404,只有通过后端向nginx发送特定信息才可以。而后端,我们是要登录系统以后才能请求的,所以就能实现我们想要的效果了。

    具体来说就是:假设我们前端部署在nginx,原本我们要访问某个静态页面:/A.html,现在不行了,要将地址改为 /api/static/getA,改而向后端请求;后端收到请求后,在响应信息头里加上一句:response.setHeader("X-Accel-Redirect", "/A.html");返回;nginx接收到响应信息后,于是将/A.html最终返回。

    现在来真的,我们要实现/projects/dzzhyj/index.html的鉴权访问。以下是实现步骤:
    在这里插入图片描述

    一、配置nginx

    server {
        listen      8001;
        server_name 192.168.0.218;
        
            。。。
        
        location /projects/dzzhyj/ {
            alias /home/gzdd_html/gzdd/projects/dzzhyj/;#物理路径
    
            location ~* \.html$ {#只设置*.html为内部访问
                internal;
            }
        }      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    二、修改前端代码

    <template>
      <div class="-map-container">
    
        <iframe src="/api/dzzhyj/redirect/dzzhyj" >iframe>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    三、增加后端代码

    @Controller
    @RequestMapping("redirect")
    public class RedirectController {
        @GetMapping("/dzzhyj")
        public void handleDzzhyj(HttpServletRequest request, HttpServletResponse response) throws Exception {
                response.setHeader("X-Accel-Redirect", "/projects/dzzhyj/index.html");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    四、运行结果

    直接访问静态页面,不行
    在这里插入图片描述
    通过后端地址可以
    在这里插入图片描述
    但后端必须登录才行
    在这里插入图片描述
    完美。

    五、小结

    这功能在nginx下才能使用。其他web服务器有没有类似机制不得而知。但我们平时开发,用vue,都直接用npm来跑,所以后端代码做点更改,判断是nginx发出的请求,才做上述处理,否则跳转:

    @Controller
    @RequestMapping("redirect")
    public class RedirectController {
        @GetMapping("/dzzhyj")
        public void handleDzzhyj(HttpServletRequest request, HttpServletResponse response) throws Exception {
            String xForwardedForHeader = request.getHeader("X-Real-IP");
            if (xForwardedForHeader != null && !xForwardedForHeader.isEmpty()) {
                // 请求经过了 Nginx
                response.setHeader("X-Accel-Redirect", "/projects/dzzhyj/index.html");
            } else {
                // 请求未经过 Nginx
                String[] hosts = request.getHeader("X-Forwarded-Host").split(",");
                String url = String.format("http://%s/projects/dzzhyj/index.html",hosts[0]);
                response.sendRedirect(url);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    其实没有方法能直接判断请求是否来自nginx,我是比较了从node发出的请求和从nginx发出的请求所包含的键值,看其中有没有包含“X-Real-IP”,简单地做了一下判断,不一定对。

    参考文章:
    Nginx的internal路径和内部重定向(X-Accel-Redirect)


    2024.02.29
    我发现,也许是兜兜转转的缘故,浏览器对这种访问可能有一些处理。当第一次因为系统初始化未完成,或其他什么原因,加载失败的话,后面就会一直失败。这时候将浏览器关掉,重新打开再访问,或者换一种浏览器,就可以成功。否则一直试,一直试,永远都找不到原因。

  • 相关阅读:
    MySQL事务控制
    力扣 895. 最大频率栈
    电脑入门:电脑键盘每个键的作用
    web3去中心化身份可验证凭证
    2022做跨境为什么要首选Lazada和shopee,现在入驻会面临哪些挑战和机遇?
    【应用统计学】描述数据分布集中趋势
    基于 Java 解释一下硬编码和非硬编码?
    Android系统10 RK3399 init进程启动(三十二) SeAndroid策略更新和验证
    浅谈react组件间通信方式
    性能测试包含哪些内容?
  • 原文地址:https://blog.csdn.net/leftfist/article/details/136262034