• Nginx 静态资源鉴权访问


    前言

    相信许多的小伙伴使用过Nginx服务器,来代理网站页面或者代理文件资源,配置简单,灵活。但是若出现像带权限的来访问Nginx的静态资源时,那简单的配置将不生效。

    原理

    img

    准备

    需要用到的知识、工具有

    1. spingBoot

    2. nginx

    3. mysql

    4. 一些文件

    开始

    Nginx配置方式

    我们来拿一个简单的Server的配置举例。

    其中会出现几个重要的信息

    1. /resource 下的 internal 属性: 写上这个属性,即代表此前缀请求不对外开放,仅可以内部访问
    2. /file 下的 proxy_pass 指提供文件鉴权服务的地址
    	server {
            listen       90; # 监听端口
            server_name  localhost; # 域名
    
    				# 静态资源前缀
            location /resource { # 静态资源访问前缀
                internal; # 内部访问!!!! 此处非常重要
                alias C:/authFile/; # 代理的静态文件目录
            }
    
            # 鉴权前缀
            location /file {
                proxy_redirect off;
                proxy_set_header Host  $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://127.0.0.1:6001; # 指定提供文件鉴权服务的地址
            }
    
    	}
    

    Mysql 表配置

    ER-图

    img

    SQL脚本

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for auth_file
    -- ----------------------------
    DROP TABLE IF EXISTS `auth_file`;
    CREATE TABLE `auth_file`  (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `file_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件地址',
      `role_id` int(255) NULL DEFAULT NULL COMMENT '角色ID',
      PRIMARY KEY (`id`) USING BTREE,
      INDEX `ROLE_ID`(`role_id`) USING BTREE,
      CONSTRAINT `ROLE_ID` FOREIGN KEY (`role_id`) REFERENCES `auth_role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
    ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for auth_role
    -- ----------------------------
    DROP TABLE IF EXISTS `auth_role`;
    CREATE TABLE `auth_role`  (
      `id` int(255) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色名称',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for auth_user
    -- ----------------------------
    DROP TABLE IF EXISTS `auth_user`;
    CREATE TABLE `auth_user`  (
      `id` int(255) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名称',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for auth_user_role
    -- ----------------------------
    DROP TABLE IF EXISTS `auth_user_role`;
    CREATE TABLE `auth_user_role`  (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `role_id` int(11) NULL DEFAULT NULL COMMENT '角色ID',
      `user_id` int(11) NULL DEFAULT NULL COMMENT '用户ID',
      PRIMARY KEY (`id`) USING BTREE,
      INDEX `U`(`role_id`) USING BTREE,
      INDEX `R`(`user_id`) USING BTREE,
      CONSTRAINT `R` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
      CONSTRAINT `U` FOREIGN KEY (`role_id`) REFERENCES `auth_role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
    ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    文件准备

    文件结构图

    img

    与之对应SQL表数据

    四张表依次为 文件表、角色表、角色用户表、用户表

    imgimgimgimg

    SpringBoot配置

    基本的DAO、实体不粘贴了,使用技术为Mybatis-plus

    yml

    server:
      port: 6001
    
    # spring 配置
    spring:
      application:
        name: auth-file
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: username
        password: password
        url: jdbc:mysql://mysql_address:port/auth-file?socketTimeout=30000&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    
    
    # mybatis-plus 配置
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      global-config:
        db-config:
          update-strategy: ignored
    

    鉴权Service

    @Service
    public class AuthService {
    
        @Resource
        UserRoleRepo userRoleRepo;
        @Resource
        FileRepo fileRepo;
    
        public Boolean auth(DownloadParams params) {
            QueryWrapper<UserRole> query = new QueryWrapper<>();
            query.eq("user_id", params.getUserId());
            List<Integer> currentUserRoles = userRoleRepo.selectList(query).stream()
                    .map(UserRole::getRoleId)
                    .collect(Collectors.toList());
            File file = fileRepo.selectById(params.getFileId());
            FileHolder.set(file.getFileName());
            if (currentUserRoles.contains(file.getRoleId())) {
                System.out.println("获得授权,开始下载");
                return true;
            } else {
                System.out.println("该用户没有文件: " + file.getFileName() + " 的下载权限");
                return false;
            }
        }
    }
    

    下载Service

    此处为重点,值得注意的是,下载的response的Header内X-Accel-Redirect 就是回调Nginx静态前缀的关键所在

    前面所提到的允许内部访问,即此处处理

    @Service
    public class DownloadService {
        @Resource
        FileRepo fileRepo;
    
        public void download(HttpServletResponse response, String fileName) {
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            response.setHeader("Content-Type", "application/octet-stream; charset=utf-8");
            response.setHeader("X-Accel-Redirect", "/resource/" + fileName);
            response.setHeader("X-Accel-Charset", "utf-8");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "No-cache");
            response.setHeader("Expires", "0");
        }
    
    }
    

    Web接口

    @RestController
    @RequestMapping("/file")
    public class NgxAuthFileHandler {
    
        @Resource
        AuthService authService;
        @Resource
        DownloadService downloadService;
    
        @GetMapping
        public String preview(DownloadParams params, HttpServletResponse response) {
            if (authService.auth(params)) {
                String fileName = FileHolder.get();
                downloadService.download(response, fileName);
                return "获得授权,开始下载";
            } else {
                String fileName = FileHolder.get();
                return "该用户没有文件: " + fileName + " 的下载权限";
            }
        }
    
    
    }
    
  • 相关阅读:
    转 MySQL权限管理
    mysql 驱动问题
    mysql issue:
    (五)容器网络 -上
    idea 快速生成代码的快捷键
    (四)容器互联
    (三)将容器变成镜像
    (二)docker的部署安装,配置,基础命令
    (一)为什么要学习docker
    Centos7 安装docker ce
  • 原文地址:https://www.cnblogs.com/JQ04/p/15905762.html
Copyright © 2020-2023  润新知