SpringBoot集成FastDFS+Nginx整合基于Token的防盗链的方法

下面是 SpringBoot 集成 FastDFS+Nginx 整合基于 Token 的防盗链的方法的完整攻略:

简介

FastDFS 是一个开源的分布式文件系统,由阿里巴巴的余庆编写,目前由开源社区进行开发,FastDFS 是基于 Linux 的文件系统,实现了一个简单的文件系统,它是以 Tracker Server 和 Storage Server 为两个服务端来运行的。Nginx 是目前非常流行的 Web 服务器软件,在线服务商也广泛采用 Nginx 作为服务端的软件之一。在使用 FastDFS 存储文件的时候,我们通常需要使用 Nginx 对文件进行访问,而防盗链可以有效的保护用户文件的安全性,防止 URL 被泄露并在未授权的情况下访问。

整合过程

  1. 添加 FastDFS 依赖

在 pom.xml 中添加 FastDFS 的依赖,这里我们使用的版本为1.27。

<dependency>
  <groupId>com.github.tobato</groupId>
  <artifactId>fastdfs-client</artifactId>
  <version>1.27.2</version>
</dependency>
  1. 配置 FastDFS 客户端

创建 FastDFS 客户端的配置类 FastDFSClientConfig,用于配置 FastDFS 链接信息和客户端工厂对象 FastDFS 基于 Tracker 的客户端。

@Configuration
public class FastDFSClientConfig {

    /**
     * Default FastDFS properties
     */
    @Value("${fastdfs.tracker-list}")
    private String trackerList;

    @Bean
    public DefaultFastFileStorageClient storageClient() {
        return new DefaultFastFileStorageClient(trackerClient());
    }

    @Bean
    public TrackerClient trackerClient() {
        return new DefaultTrackerClient();
    }

    @Bean
    public ConnectionPoolConfig connectionPoolConfig() {
        ConnectionPoolConfig connectionPoolConfig = new ConnectionPoolConfig();
        connectionPoolConfig.setMinPoolSize(1);
        connectionPoolConfig.setMaxPoolSize(10);
        connectionPoolConfig.setMaxIdleTime(3600);
        return connectionPoolConfig;
    }

    @Bean(initMethod = "init")
    public FastFileStorageClientFactory storageClientFactory() {
        FastFileStorageClientFactory factory = new FastFileStorageClientFactory();
        factory.setConnectionPoolConfig(connectionPoolConfig());
        factory.setStorageClient(storageClient());
        factory.setTrackerClient(trackerClient());
        return factory;
    }
}
  1. 配置 Nginx

在 Nginx 中配置 FastDFS 模块和防盗链模块,Nginx 需要定时更新防盗链 Token 配置,以保证访问安全性。

# nginx-fastdfs.conf

worker_processes auto;
events {
    worker_connections 1024;
}

http {
    default_type       application/octet-stream;
    sendfile            on;
    # gzip              on;
    server {
        listen       80;
        server_name  localhost;
        access_log   logs/access.log  access;
        location ~ /group([0-9]+)/M00/(.*)$ {
            alias /data/fastdfs/storage/data/data/$1/$2;
        }

        location /group1/M00/ {
            ngx_fastdfs_module;
            ngx_fastdfs_tracker $tracker_server;
            ngx_fastdfs_store_path /data/fastdfs/storage/data;
        }

        location / {
            root   html;
            add_header 'Access-Control-Allow-Origin' '*';
        }

        location /download {
            external;
            internal;
            add_header Content-Disposition "attachment;filename=$arg_filename;";
        }

        # token
        location /upload {
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Headers Origin, X-Requested-With, Content-Type, Accept;
            internal;
            set $token_hash "";
            if ($http_secret_key) {
                set $token_hash $http_secret_key;
            }
            set $s $query_string;
            if ($args) {
                set $s "${s}&";
            }
            set $s "${s}token_hash=${token_hash}";
            set_md5 $token $s;
            set $arg_token $token;
        }
    }
}
  1. 集成 Token 配置

创建 Token 的验证工具类 TokenUtils,用于生成和验证 Token。

@Component
public class TokenUtils {

    /**
     * 密钥
     */
    private static final String SECRET_KEY = "MY_SECRET_KEY";

    /**
     * 生成 Token
     *
     * @param path
     * @return
     */
    public static String generateToken(String path) {
        Long timestamp = System.currentTimeMillis() / 1000L;
        String tokenMeta = path + "&" + SECRET_KEY + "&" + timestamp.toString();
        String token = DigestUtils.md5Hex(tokenMeta);
        return token + "&" + timestamp;
    }

    /**
     * 验证 Token
     *
     * @param path
     * @param token
     * @return
     */
    public static boolean verifyToken(String path, String token) {
        String[] tokenArr = token.split("&");
        if (tokenArr.length != 2) {
            return false;
        }
        String signToken = tokenArr[0];
        Long timestamp = Long.valueOf(tokenArr[1]);
        Long currentTimestamp = System.currentTimeMillis() / 1000L;
        if (currentTimestamp - timestamp > 60 * 60) {
            return false;
        }
        String tokenMeta = path + "&" + SECRET_KEY + "&" + timestamp.toString();
        String calToken = DigestUtils.md5Hex(tokenMeta);
        if (StringUtils.equals(signToken, calToken)) {
            return true;
        } else {
            return false;
        }
    }
}
  1. 编写防盗链拦截器

创建文件防盗链拦截器 DownloadTokenInterceptor,用于拦截文件下载的请求,验证 Token 的有效性和访问权限。

@Component
public class DownloadTokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 是否有 Secret Key
        if (StringUtils.isBlank(request.getHeader("Secret-Key"))) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        // 获取 Token,格式为:ts&token
        String token = request.getHeader("Token");

        // 验证 Token
        if (!TokenUtils.verifyToken(request.getRequestURI(), token)) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Token is invalid");
            return false;
        }

        return true;
    }
}
  1. 使用 TokenInterceptor 拦截器

在 SpringBoot 应用中注册 DownloadTokenInterceptor 拦截器,并将拦截器加在需要拦截的路径下。

@Configuration
public class ConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Autowired
    private DownloadTokenInterceptor downloadTokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(downloadTokenInterceptor).addPathPatterns("/download/**");
        super.addInterceptors(registry);
    }
}

至此,SpringBoot 集成 FastDFS+Nginx 整合基于 Token 的防盗链的方法已经完成。

示例

示例1:文件上传

  1. 前端页面示例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>文件上传测试</title>
</head>
<body>
  <form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <button type="submit">Submit</button>
  </form>
</body>
</html>
  1. 文件上传控制器示例:
@Controller
public class FileUploadController {

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws IOException {
        String groupName = "group1";
        String filepath = "test.jpg";
        StorePath storePath = storageClientFactory.getStorageClient().uploadFile(groupName, file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()));
        return storePath.getFullPath();
    }
}

示例2:文件下载

  1. 前端页面示例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>文件下载测试</title>
</head>
<body>
  <form action="http://localhost:8080/download" method="post">
    <input type="hidden" name="filename" value="test.jpg" />
    <input type="hidden" name="token_hash" value="123" />
    <button type="submit">Submit</button>
  </form>
</body>
</html>
  1. 文件下载控制器示例:
@Controller
public class FileDownloadController {

    @PostMapping("/download")
    public void download(String filename, String token_hash, HttpServletResponse response) throws Exception {
        OutputStream out = null;
        InputStream in = null;
        response.setHeader("Content-disposition", "attachment;filename=" + filename);
        response.setContentType("application/octet-stream");
        String token = token_hash + "&" + TokenUtils.generateToken(filename);
        String url = "http://localhost/group1/M00/00/00/" + filename + "?" + "token=" + token;
        try {
            in = new URL(url).openStream();
            out = response.getOutputStream();
            byte[] buffer = new byte[2048];
            int len = 0;
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            out.flush();
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}

希望我的讲解能对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot集成FastDFS+Nginx整合基于Token的防盗链的方法 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java基础-Java基本数据类型

    Java基础-Java基本数据类型 Java中的数据类型分为两类: 基本数据类型和引用数据类型。基本数据类型共8种,分别是byte、short、int、long、float、double、boolean、char。本文将详细介绍Java的基本数据类型。 byte byte类型是最小的数据类型,占1个字节(byte),取值范围是-128到127。当我们需要存储…

    Java 2023年5月26日
    00
  • 基于Java回顾之I/O的使用详解

    基于Java回顾之I/O的使用详解 什么是I/O I/O是输入输出的缩写,Java中I/O指的是从输入源读取数据,或将数据输出到输出目标。Java提供了大量的I/O类和接口,以方便我们处理各种输入和输出。 I/O的分类 输入流 输入流用于从输入源读取数据,Java提供了多种输入流,常用的有: FileInputStream:从文件中读取数据。 ByteArr…

    Java 2023年5月26日
    00
  • 详解springboot采用多数据源对JdbcTemplate配置的方法

    请您耐心阅读以下攻略,我将分为以下几个部分进行讲解: Spring Boot多数据源配置 JdbcTemplate添加多数据源支持 示例代码 1. Spring Boot多数据源配置 在Spring Boot中配置多数据源其实非常简单,只需要在application.properties(或application.yml)中配置多组数据源即可。以下是一个简单…

    Java 2023年5月20日
    00
  • springboot springmvc抛出全局异常的解决方法

    下面是详细讲解“springboot springmvc抛出全局异常的解决方法”的完整攻略。 1. 场景描述 在开发Spring Boot和Spring MVC项目时,我们经常需要处理程序运行时的异常,这些异常可能会在控制器、服务或Spring Bean中发生。当运行时发生异常时,Spring Boot框架会抛出默认的异常界面,可能包含敏感信息,这不是我们想…

    Java 2023年5月27日
    00
  • jsp实现仿QQ空间新建多个相册名称并向相册中添加照片功能

    实现仿QQ空间新建多个相册名称并向相册中添加照片功能需要进行以下步骤: 准备工作 确定基础环境:使用JSP,需要安装Java和Tomcat等环境。 安装数据库:本文以MySQL为例进行讲解,需要安装MySQL数据库,并创建相应的数据库和表格。 创建数据库和表格 在MySQL中创建相应的数据库,例如“photo_album”。 在该数据库下创建两个表格:一个用…

    Java 2023年6月15日
    00
  • java实现计算器功能

    Java是一种高级编程语言,通过使用Java代码可以实现计算器的功能。下面是实现计算器功能的详细攻略: 1. 设计思路 要实现计算器的功能,需要考虑以下问题: 如何获取用户的输入; 如何进行计算; 如何将计算结果输出给用户。 解决以上问题,我们可以设计一个基本的计算器功能,并将其分为三个部分: 一个界面,用于显示计算器的操作和计算结果; 一个模块,用于读取用…

    Java 2023年5月18日
    00
  • 手把手带你实现一个萌芽版的Spring容器

    手把手带你实现一个萌芽版的Spring容器 什么是Spring容器 Spring容器是Spring框架的核心组件之一,主要负责管理Bean的生命周期,维护Bean之间的依赖关系,并提供各种应用上下文服务,是Spring框架的核心所在。Spring容器有多种类型,包括ApplicationContext、BeanFactory等。 实现一个Spring容器 实…

    Java 2023年5月19日
    00
  • java.nio.file.WatchService 实时监控文件变化的示例代码

    下面是详细的讲解: WatchService 介绍 Java NIO 中的 WatchService 可以用来监测文件系统的变化。它允许程序在某个目录下监测文件的变化,包括新增、修改和删除事件。 示例代码 下面我们来看两个使用 WatchService 实现实时监控文件变化的示例。 示例一:监控指定目录下的文件变化 首先,创建一个 Watcher 类用于实现…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部