利用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

bash 复制代码
server {
    listen      8001;
    server_name 192.168.0.218;
    
        。。。
    
    location /projects/dzzhyj/ {
        alias /home/gzdd_html/gzdd/projects/dzzhyj/;#物理路径

        location ~* \.html$ {#只设置*.html为内部访问
            internal;
        }
    }      
}

二、修改前端代码

html 复制代码
<template>
  <div class="-map-container">
<!--    <iframe src="/projects/dzzhyj/index.html" ></iframe> -->
    <iframe src="/api/dzzhyj/redirect/dzzhyj" ></iframe>
  </div>
</template>

三、增加后端代码

java 复制代码
@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");
    }
}

四、运行结果



完美。

五、小结

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

java 复制代码
@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);
        }
    }
}

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

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

相关推荐
木易 士心1 天前
Nginx 基本使用和高级用法详解
运维·javascript·nginx
siriuuus2 天前
Nginx IP 透传
网络·nginx
40kuai2 天前
nginx server_tokens 和proxy_hide_header的差别
运维·nginx
小池先生3 天前
服务请求出现偶发超时问题,经查服务本身没问题,问题出现在nginx转发。
运维·服务器·nginx
Java水解3 天前
Nginx平滑升级与location配置案例详解
后端·nginx
心灵宝贝3 天前
nginx-1.16.1-2.p01.ky10.sw_64.rpm 安装教程(详细步骤,适用于Kylin V10/SW64架构)
nginx·架构·kylin
用户31187945592184 天前
nginx-1.16.1-2.p01.ky10.sw_64.rpm 安装教程(详细步骤,适用于Kylin V10/申威SW64架构)
nginx
stark张宇4 天前
攻克 CRMRB 部署难点:从 PHP 扩展、数据库配置到进程守护
nginx·centos·php
罗政4 天前
【免费】轻量级服务器centos监控程序+内存+cpu+nginx+适合小型站长使用
服务器·nginx·centos
椎4955 天前
苍穹外卖前端nginx错误之一解决
运维·前端·nginx