fastDFS+SpringBoot实现文件防盗链

news/2024/9/29 19:29:00

FastDFS内置防盗链采用Token的方式。Token是带时效的,也就是说在设定的时间范围内,比如1分钟,token是有效的。token包含了文件id、时间戳ts和密钥。
FastDFS在URL中带上当前时间戳和带时效的token,参数名分别为ts和token。Token的生成和校验都是在服务端,因此不会存在安全问题。

例如:

http://你的IP/meng/M00/00/00/rBFE2VwohBOAOrnIAABDRU16ivg948.png?token=f48b02095128da73e43006d2b53f0001&ts=1546159147

配置文件说明

1、http.conf中防盗链相关的几个参数如下:

# cd /etc/fdfs
# vim /etc/fdfs/http.conf
# if use token to anti-steal
# default value is false (0)   
# 是否做token检查,缺省值为false。
http.anti_steal.check_token=true# token TTL (time to live), seconds
# default value is 600
# TTL,即生成token的有效时长(秒)
http.anti_steal.token_ttl=120# secret key to generate anti-steal token
# this parameter must be set when http.anti_steal.check_token set to true
# the length of the secret key should not exceed 128 bytes
# 生成token的密钥,尽量设置得长一些,千万不要泄露出去
http.anti_steal.secret_key=FastDFS1234567890# return the content of the file when check token fail
# default value is empty (no file sepecified)
# 检查失败,返回的文件内容,需指定本地文件名
http.anti_steal.token_check_fail=/home/fileError.png

需重启 tracker、storage 和 nginx

# fdfs_trackerd /etc/fdfs/tracker.conf
# fdfs_trackerd /etc/fdfs/tracker.conf restart
waiting for pid [23891] exit ...
starting ...
# fdfs_storaged /etc/fdfs/storage.conf
# fdfs_trackerd /etc/fdfs/tracker.conf restart
waiting for pid [26848] exit ...
starting ...
# ./nginx -s reload
ngx_http_fastdfs_set pid=26832

2、application-dev.properties

# fastDFS 
fdfs.so-timeout=1501
fdfs.connect-timeout=601
fdfs.thumb-image.width=150
fdfs.thumb-image.height=150
fdfs.web-server-url=你的IP/
fdfs.tracker-list[0]=你的IP:22122
fdfs.http.anti_steal_token = true
fdfs.http.secret_key = FastDFS1234567890

项目中增加依赖

<!-- fastDFS -->
<dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId><version>1.26.2</version>
</dependency>
<dependency><groupId>net.oschina.zcx7878</groupId><artifactId>fastdfs-client-java</artifactId><version>1.27.0.0</version>
</dependency>

引入fastDFS配置

import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;import com.github.tobato.fastdfs.FdfsClientConfig;@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)// 解决jmx重复注册bean的问题
public class ComponetImport {// 导入依赖组件
}

工具类

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.web.multipart.MultipartFile;import com.github.tobato.fastdfs.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;@Component
public class FastDFSClient {@Autowiredprivate FastFileStorageClient storageClient;@Autowiredprivate FdfsWebServer fdfsWebServer;/*** 上传文件* @param file 文件对象* @return 文件访问地址* @throws IOException*/public String uploadFile(MultipartFile file) throws IOException {StorePath storePath = storageClient.uploadFile(file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);return getResAccessUrl(storePath);}/*** 上传文件* @param file 文件对象* @return 文件访问地址* @throws IOException*/public String uploadFile(File file) throws IOException {FileInputStream inputStream = new FileInputStream (file);StorePath storePath = storageClient.uploadFile(inputStream,file.length(), FilenameUtils.getExtension(file.getName()),null);return getResAccessUrl(storePath);}/*** 将一段字符串生成一个文件上传* @param content 文件内容* @param fileExtension* @return*/public String uploadFile(String content, String fileExtension) {byte[] buff = content.getBytes(Charset.forName("UTF-8"));ByteArrayInputStream stream = new ByteArrayInputStream(buff);StorePath storePath = storageClient.uploadFile(stream,buff.length, fileExtension,null);return getResAccessUrl(storePath);}// 封装图片完整URL地址private String getResAccessUrl(StorePath storePath) {String fileUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();return fileUrl;}/*** 下载文件* @param fileUrl 文件url* @return*/public byte[]  download(String fileUrl) {String group = fileUrl.substring(0, fileUrl.indexOf("/"));String path = fileUrl.substring(fileUrl.indexOf("/") + 1);byte[] bytes = storageClient.downloadFile(group, path, new DownloadByteArray());return bytes;}/*** 删除文件* @param fileUrl 文件访问地址* @return*/public void deleteFile(String fileUrl) {if (StringUtils.isEmpty(fileUrl)) {return;}try {StorePath storePath = StorePath.praseFromUrl(fileUrl);storageClient.deleteFile(storePath.getGroup(), storePath.getPath());} catch (FdfsUnsupportStorePathException e) {e.getMessage();}}}

文件的上传、下载 与 访问获取的 token

import org.apache.commons.io.IOUtils;
import org.csource.common.MyException;
import org.csource.fastdfs.ProtoCommon;
import org.meng.project.common.FileUtil;
import org.meng.project.entity.Filesource;
import org.meng.project.service.ExcelService;
import org.meng.project.service.FileService;
import org.meng.project.util.FastDFSClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Controller
@RequestMapping("/fdfs")
public class FastDFSController {@Autowiredprivate FastDFSClient fdfsClient;@Value("${fdfs.web-server-url}")private String fastdfsUrl;@Value("${fdfs.http.secret_key}")private String fastdfsToken;/*** 文件上传* @param file* @return* @throws Exception*/@RequestMapping("/upload/file")@ResponseBodypublic Map<String,Object> upload(@RequestParam("file") MultipartFile file, Model model) throws Exception{Map<String,Object> resultMap = new HashMap<>();String url = null;try {url = fdfsClient.uploadFile(file);resultMap.put("code", 200);resultMap.put("message", "上传成功");resultMap.put("url", url);System.out.println(url);} catch (Exception e) {// TODO: handle exceptionresultMap.put("status", 500);resultMap.put("message", "上传异常!");}return resultMap;}/*** 文件下载* @param fileUrl  url 开头从组名开始* @param response* @throws Exception*/@RequestMapping(value="/download", method = {RequestMethod.GET})public void  download(HttpServletResponse response, HttpServletRequest request) throws Exception{String fileUrl = request.getParameter("fileUrl");byte[] data = fdfsClient.download(fileUrl);response.setCharacterEncoding("UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("test.jpg", "UTF-8"));// 写出ServletOutputStream outputStream = response.getOutputStream();IOUtils.write(data, outputStream);}/*** 生成访问链接*/@RequestMapping(value="/location", method = {RequestMethod.GET})public String location(HttpServletResponse response, HttpServletRequest request, Model model) {String fileUrl = request.getParameter("location");System.out.println(fileUrl);//tokenString token = fastdfsToken;String IP = fastdfsUrl;fileUrl = getToken(fileUrl,token,IP);model.addAttribute("Url", fileUrl);return "tools/uploadfile";}/*** 获取访问服务器的token,拼接到地址后面** @param fid 文件路径 group1/M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg* @param secret_key 密钥* @return 返回token,如: token=078d370098b03e9020b82c829c205e1f&ts=1508141521*/public static String getToken(String fid, String secret_key, String IP){String substring = fid.substring(fid.indexOf("/")+1);//unix时间戳 以秒为单位int ts = (int) (System.currentTimeMillis() / 1000);String token=new String();try {token= ProtoCommon.getToken(substring, ts, secret_key);} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (MyException e) {e.printStackTrace();}StringBuilder sb = new StringBuilder();sb.append(IP);sb.append(fid);sb.append("?token=").append(token);sb.append("&ts=").append(ts);//System.out.println(sb.toString());return sb.toString();}
}

效果

1、上传

2、下载

3、获取访问链接:

访问效果图:


原文章地址:
https://blog.csdn.net/W_Meng_H/article/details/85402879

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/45363.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

PyQT5之QStackedWidget

QStackWidget堆栈窗口 from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sysclass stackwidgetDemo(QTabWidget):def __init__(self):super(stackwidgetDemo, self).__init__()self.setWindowTitle("堆栈控件QStackWidget&quo…

安装charles,抓包工具

1、下载安装 Download a Free Trial of Charles • Charles Web Debugging Proxy (charlesproxy.com 2.激活charles 2.1、方法一 Charles破解工具 (zzzmode.com),一个在线激活的地址 激活 Registered Name: 坚固的大兴License Key: f9bb35c1705bcef85a 2.2、方法二View Co…

RPA京麦咚咚批量发送消息

京麦咚咚发送消息,首先我们需要确定给谁发,发送什么内容给谁发:可以传入京东用户名、京东订单号。咚咚将通过此条件进行搜索进入会话框 发送什么内容:批量发送信息给不同的用户,比如给不同的订单用户发送其相应的物流单号 这里我们以“给不同的订单用户发送其相应的物流单…

计算机组成原理学习 Part 1

计算机系统 组成 \[计算机系统 \begin{cases} 硬件 &\text 计算机的实体,如主机、外设等\\ 软件 &\text 由具有各类特殊功能的信息(程序)组成 \end{cases} \]\[软件 \begin{cases} 系统软件 & \text 用来管理整个计算机系统\\ &\text 语言处理程序\\ &…

Flutter环境搭建

最近,项目不是那么紧了,抽空学习了一下Flutter,Flutter开发搭建环境是第一步,记录下搭建环境过程中遇到的问题及解决的方式方法。 1.下载Flutter官方sdk 在 Windows 操作系统上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 可参照链…

技术解密Java Chassis 3超实用的可观测性

本文将解密如何使用Java Chassis 3可观测能力来快速定位问题,以及这个能力是如何构建起来的。本文分享自华为云社区《Java Chassis 3技术解密:实用的可观测性》,作者:liubao68。 狭义的可观测性,指日志、调用链和指标,广义的可观测性则包含更多的内容,一般的,应用程序暴…

charles证书过期处理

证书过期 1.打开charles 重置证书 2.安装证书 3.安装后会自动打开钥匙串,把旧的证书删掉,会出现新的证书 4.双击证书,点击全部信任 5.重启charles即可

2024年6月中国数据库排行榜:榜单前三又迎新,金仓华为云跃升展雄心

墨天轮6月排行榜解读文章已发布!本月榜单前10再现变动、开源数据库继续引领潮流,此外更有一批数据库表现亮眼、迈向国际舞台。一起来看更多排名情况与解读!入夏之际,2024 年 6 月中国数据库排行榜揭晓,各大数据库产品的表现格外引人注目。榜单显示,开源数据库继续引领潮流…