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日

相关文章

  • 详解如何在SpringBoot中自定义参数解析器

    下面我将详细讲解如何在SpringBoot中自定义参数解析器。 一、参数解析器 在SpringBoot中,我们可以通过继承HandlerMethodArgumentResolver接口来自定义参数解析器。 public interface HandlerMethodArgumentResolver { // 判断是否支持该参数类型的解析 boolean su…

    Java 2023年6月16日
    00
  • 跨站脚本攻击XSS原理与防范实例分析

    跨站脚本攻击XSS原理与防范实例分析 XSS攻击原理 跨站脚本攻击(XSS)是通过在web应用程序中注入恶意脚本来攻击用户的一种常见安全漏洞。攻击者可将攻击代码注入到正常的web页面中,一旦被用户浏览器执行,就能够窃取用户的敏感信息或者利用用户的身份进行恶意操作。 XSS攻击通常分为以下三种类型: 存储型攻击:攻击者将恶意脚本注入到web应用程序中的数据库中…

    Java 2023年6月16日
    00
  • 防止xss和sql注入:JS特殊字符过滤正则

    防止 XSS 和 SQL 注入攻击是 web 应用程序开发中非常重要的一部分。在前端中,JavaScript 特殊字符过滤正则表达式可以帮助我们完成这项工作。 下面是一份完整的防止 XSS 和 SQL 注入攻击的攻略: 1. 什么是 XSS 和 SQL 注入攻击 XSS(Cross Site Scripting)攻击是一种恶意代码注入攻击,攻击者使用 Jav…

    Java 2023年6月16日
    00
  • Java实现简单修改文件名的方法分析

    下面是“Java实现简单修改文件名的方法分析”的完整攻略。 1. 概述 在Java中,我们可以使用File类的renameTo()方法来修改文件的名称。renameTo()方法能够将一个文件重命名为一个指定的目录路径或文件路径名。本篇攻略将详细介绍使用Java修改文件名的方法。 2. renameTo()方法的使用 2.1 单个文件重命名 下面是一个单个文件…

    Java 2023年5月19日
    00
  • java中\t,\n,\r,\b,\f 的作用及说明

    当我们在Java程序中编写字符串时,可能会使用一些特殊字符来表示某些特殊的字符或操作。在Java中,一些特殊字符会有特殊的含义和作用。以下是Java中一些常用的特殊字符: \t:制表符 制表符\t用于在输出中设置水平制表位置。它将当前输出位置移到下一个制表符位置,这样下一个字符将在该位置打印。示例代码如下: System.out.println("…

    Java 2023年5月26日
    00
  • Mybatis联合查询的实现方法

    下面是对于Mybatis联合查询的实现方法的详细讲解及示例。 1. 联合查询的概念 Mybatis的联合查询实际上是多表查询的一种实现方式,也就是说,它是通过对多个数据表进行连接查询,然后再将查询结果进行合并,最终得到一个包含所有所需数据的结果集。联合查询通常用于查询复杂的业务需求,例如需要返回关联表或多个表中的信息的场合。 2. 联合查询的实现方法 在My…

    Java 2023年5月20日
    00
  • 相册管理系统(Java表单+xml数据库存储)

    相册管理系统(Java表单+xml数据库存储)是一个使用Java开发的Web应用程序,可以让用户上传和查看图像,并能够对这些图像进行管理。该系统使用了Java表单和xml数据库存储进行数据交互和管理。下面是该系统的完整攻略。 前提条件 在开始使用相册管理系统之前,您需要确保您已经满足以下要求: 电脑已经安装了Java开发环境和Tomcat服务器 您已经掌握了…

    Java 2023年5月20日
    00
  • Session过期后实现自动跳转登录页面

    要实现Session过期后自动跳转到登录页面,需要进行以下步骤: 1. 设置Session过期时间 在服务器端的配置文件中设置Session过期的时间,例如设置为30分钟。具体的配置方式可以因服务器而异,例如在PHP中可以通过php.ini文件中的session.gc_maxlifetime参数来设置过期时间。在JAVA中可以通过web.xml文件或者代码来…

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