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日

相关文章

  • 如何自定义hibernate validation注解示例代码

    自定义Hibernate Validation注解可以通过以下步骤来完成: 1. 定义注解 自定义注解需要使用@Constraint注解进行标记,并提供以下信息: validatedBy:用于指定执行验证逻辑的验证器类; message:用于指定验证不通过时返回的错误消息; groups:用于指定验证所属的组,默认情况下采用javax.validation.…

    Java 2023年5月20日
    00
  • java中struts2实现文件上传下载功能

    下面是java中struts2实现文件上传下载功能的完整攻略: 一、文件上传功能的实现 1. 安装文件上传插件 在struts2中实现文件上传功能需要依赖文件上传插件,可以通过以下方式进行安装: 在pom.xml中加入以下依赖: <dependency> <groupId>org.apache.struts</groupId&g…

    Java 2023年5月20日
    00
  • 一些实用的TAB效果

    一些实用的TAB效果可以通过CSS和JavaScript实现。下面为您提供详细的攻略和两个示例。 实现步骤 在HTML中创建一个元素,用来包含选项卡切换按钮和内容区域。 在CSS中为选项卡切换按钮和内容区域定义样式。 在JavaScript中编写代码,给每个选项卡按钮添加点击事件,动态切换内容区域的显示。 下面是两个示例: 示例一 该示例实现点击选项卡切换按…

    Java 2023年6月15日
    00
  • springboot 自定义权限标签(tld),在freemarker引用操作

    下面是完整攻略: 1. 首先创建Spring Boot项目 可以使用Spring Initializr创建一个新的Spring Boot项目,选择Web和Freemarker作为依赖项。 2. 添加依赖项 在pom.xml文件中添加以下依赖项: <dependency> <groupId>org.springframework.boo…

    Java 2023年6月15日
    00
  • 浅谈对象与Map相互转化

    关于“浅谈对象与Map相互转化”的攻略,我将分为以下三个部分进行讲解: 对象转Map Map转对象 示例说明 对象转Map 在JavaScript中,我们可以使用Object.entries()方法快速地将一个对象转化为Map。 const obj = { name: "Tom", age: 18 }; const map = new M…

    Java 2023年5月26日
    00
  • (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    为了使网站的用户可以在网页上播放视频和音频文件,可以使用嵌入式播放器来实现。常用的嵌入式播放器包括 HTML5 audio 和 video 元素、Flash 播放器、以及第三方嵌入式播放器等。本攻略将为您介绍如何在 JSP/HTML 网页上嵌入这些播放器。 HTML5 Audio 和 Video 元素 HTML5 audio 和 video 元素是 HTML…

    Java 2023年6月15日
    00
  • ASP.NET微信公众号添加菜单

    下面我将为您详细讲解“ASP.NET微信公众号添加菜单”的完整攻略。 1. 准备工作 首先,在进行微信公众号开发之前,我们需要准备以下工作: 申请微信公众号账号,并获取到对应的AppID和AppSecret。 下载微信公众号开发者工具,该工具可帮助我们进行调试和预览。 创建一个ASP.NET项目,并引入微信公众平台SDK。 2. 添加菜单 在准备工作完成后,…

    Java 2023年5月23日
    00
  • Springboot导出文件,前端下载文件方式

    下面是Spring Boot导出文件、前端下载文件的攻略。 问题 有时候我们需要从Spring Boot应用中导出一些文件,如Excel、PDF或者其他格式的文件。我们如何通过前端将这些文件下载到本地? 导出文件 在Spring Boot中,我们可以借助一些开源组件实现文件的导出,常见的包括Apache POI、iText等。这里以Apache POI导出E…

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