springboot集成FastDFS使用实现防盗链功能
关于FastDFS
FastDFS是一个高性能的分布式⽂件系统。
FastDFS是由Tracker server(追踪调度服务器) 和 Storage server(文件存储服务器)组成。
Storage server(文件存储服务器)又是由多个组构成
Tracker server(追踪调度服务器)
Tracker server(追踪调度服务器),作⽤是负载均衡和调度,通过 Tracker server 在⽂件上传时可以根据⼀些策略找到Storage server 提供⽂件上传服务,所以将 tracker server称为追踪服务器或调度服务器。
Storage server(文件存储服务器)
Storage server(文件存储服务器) 作⽤是⽂件存储,客户端上传的⽂件最终存储在 Storage 服务器上,Storage server 没有实现⾃⼰的⽂件系统⽽是利⽤操作系统的⽂件系统来管理⽂件,所以将storage称为存储服务器。
Group(组)
1.由于Storage server(文件存储服务器)是用来存储文件的,具有容量限制,为了解决该问题,提出扩容分组,所以延伸出组的概念。
2.每个组存放部分文件,且每个组之间保存的⽂件是不同的。
3.为保证每个组内的节点服务高可用,允许组内构建存储服务器集群,每个组内部可以有多个成员,组成员内部保存的内容是⼀样的,组成员的地位是⼀致的,没有主从的概念。
4.由于文件存放在每个组的节点上,所以为了方便http访问调用,每个Storage server还要绑定一个nginx。
5.所有的组加起来是一个完成的Storage server(文件存储服务器)。
docker安装FastDFS
- 1.安装步骤
1.拉取fastdfs镜像
docker pull delron/fastdfs
2.创建Tracker server(追踪调度服务器)容器
提示
:在指定虚拟机镜像之后,还需要添加tracker命令,这样镜像就会根据tracker命令启动tracker服务
docker run -d --name tracker --net=host -p 22122:22122 -v /var/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
–net=host : 将虚拟机的网络应用于容器,也就是说和宿主机网络一致
3.Storage server(文件存储服务器),需要指定Tracker 的ip和端口
提示
:在指定虚拟机镜像之后,还需要添加storager命令,这样镜像就会根据storage命令启动storage服务
docker run -d --name storage --net=host -p 8888:8888 -p 23000:23000 -e TRACKER_SERVER=192.168.130.160:22122 -e GROUP_NAME=group1 -v /var/fastdfs/storage:/var/fdfs delron/fastdfs storage
GROUP_NAME=group1 : 指定服务器在组group1中或者新增一个组叫group1,如果想要增加新的组用于扩容 ,再次运行该命令,更换新组名即可。
–net=host : 将虚拟机的网络应用于容器,也就是说和宿主机网络一致
- 2.修改nginx配置
storage内部已经集成了nginx,这里的nginx可以使图片在浏览器中访问到
1.进入Storage容器内
提示
:进入Storage容器内【cd /etc/fdfs/ 】也有Storage和Tracker的配置
docker exec -it storage /bin/bash
2.编辑文件【nginx.conf】文件
vi /usr/local/nginx/conf/nginx.conf
3.如果i进行了配置修改 则需要重启
docker restart storage
使用步骤
1.导包
<!--fastdfs文件存储-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.7</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
2.添加配置
在【application.yml】添加配置
fdfs:
so-timeout: 1500 #读取超时时间
connect-timeout: 600 #连接超时时间
thumb-image: #缩略图参数
width: 150
height: 150
tracker-list: 192.168.136.160:22122 #tracker服务器地址 可配置多个
web-server-url: http://192.168.136.160:8888 #访问路径 storage中nginx地址
测试
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.server.AppServerApplication;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File;
import java.io.IOException;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AppServerApplication.class)
public class FastDFSTest {
@Autowired
protected FastFileStorageClient storageClient;
@Autowired
private FdfsWebServer fdfsWebServer;
@Test
public void testUpload() {
String path = "D:\\IMAGE\\2e8e06bd-bfe3-4af3-9540-83eb20982656.jpg";
File file = new File(path);
try {
//上传图片
StorePath storePath = this.storageClient.uploadFile(FileUtils.openInputStream(file), file.length(), "jpg", null);
//拼接路径 可通过该路径访问上传的照片 http://192.168.136.160:8888/group1/M00/00/00/wKiIoGMB7PmAUPZZAAHMYGEwMhg147.jpg
String url = fdfsWebServer.getWebServerUrl() + "/" + storePath.getFullPath();
System.out.println(url);
} catch (IOException e) {
e.printStackTrace();
}
}
}
fastdfs开启防盗链功能
实现原理
1.fastdfs是一个分布式文件系统,如果我们的fastdfs部署在外网,那么任何一个人知道了我们的上传接口,那么它就可以文件的上传和访问。那么我们如何阻止他人访问我们fastdfs服务器上的文件呢?因此就需要使用fastdfs的防盗链功能。
2.原理:fastdfs的防盗链是通过token机制来实现的。当我们开启防盗链功能后,需要在url后增加2个额外的参数token和ts。token和ts的生成都是需要在服务端。
开启防盗链
FastDFS扩展模块内置了通过token来实现防盗链的功能。开启防盗链后,访问文件是需要在url中加两个参数:token和ts。ts为时间戳,token为系统根据时间戳和密码生成的信物。
进入 storage
容器 打开:
vi /etc/fdfs/http.conf
# true 表示开启防盗链
http.anti_steal.check_token = true
# token的过期时间,单位为秒
http.anti_steal.token_ttl = 300
# 密钥,不可泄漏,用于生成token
http.anti_steal.secret_key = thisisasecuritykey
# 当图片拒绝访问后,显示的图片,此图片需要可访问,不然可能会出现问题,放到容器里 使用 chmod -R 777 /data/fastdfs/404.jpg 授权
http.anti_steal.token_check_fail = /data/fastdfs/404.jpg
http.anti_steal.token_check_fail 指定的图片需要可访问,否则可能会出现问题,可以对应
storage
容器的nginx 日志
查看,包括调试网络
重启nginx
/usr/local/nginx/sbin/nginx -s reload
Java代码生成授权token
1.token生成规则
token = md5(文件ID+私钥+时间戳) 文件ID:不能包含group
group1/M00/00/00/wKh5iWNBl7-AKvj1AAAwWD4VeAg577.jpg
`需要替换成`
M00/00/00/wKh5iWNBl7-AKvj1AAAwWD4VeAg577.jpg
私钥:需要和 /etc/fdfs/http.conf 中的 http.anti_steal.secret_key 值一致
时间戳:单位秒
2.java生成token
/**
* 生成防盗链token
* @param remoteFilename 文件路径,不带group:M00/00/00/wKg4C1tFmTWAFPKBAADdeFFxlXA240.png
* @param httpHost 文件服务器web访问地址
* @param secretKey 密码
* @return
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
* @throws MyException
*/
public static String getSourceUrl(String remoteFilename, String httpHost,String secretKey) throws UnsupportedEncodingException, NoSuchAlgorithmException, MyException {
int lts = (int)(System.currentTimeMillis() / 1000);
String token = ProtoCommon.getToken(remoteFilename, lts, secretKey); //初始化secret_key
return httpHost + "/" + remoteFilename + "?token=" + token + "&ts=" + lts;
}
/**
* 获取分组id
*
* @param fileUrl 文件地址
* @return 分组id
*/
public static String getGroupId(String fileUrl) {
if (fileUrl.indexOf("/group") == 0) {
fileUrl = fileUrl.substring(fileUrl.indexOf("/") + 1);
} else if (fileUrl.contains("http")) {
int index = fileUrl.indexOf("group");
if (index != -1) {
fileUrl = fileUrl.substring(index);
}
} else {
int index = fileUrl.indexOf("group");
if (index != -1) {
fileUrl = fileUrl.substring(index);
}
}
return fileUrl;
}
得到
http://192.168.56.10:8888/M00/00/00/wKg4C1tFmTWAFPKBAADdeFFxlXA240.png?token=2fd428c6acc14126239e3a7d7d1d872b&ts=153
测试
正确的token请求
错误的token请求
问题
1. 实现了文件上传,但是通过Nginx去访问文件就报错请求出现:ERROR - file: ../fastdfs-nginx-module/src/common.c errno: 13, error info: Permission denied
解决办法:
对storage的新挂载的data2(本系统新建的文件夹是data2)赋权限。执行命令 chmod -R 777 data2/
即可,最好是777
2.fastdfs的常见错误:getStoreStorage fail, errno code: 0,getStoreStorage fail, errno code:2@TOC
解决办法:
- 首先看先注册中心配置的文件地址与服务器中/etc/fdfs/storage.conf的地址是否一致
2.如果以上配置正确且一致,重启tracker和重启storage
重启命令:
tracker:fdfs_trackerd /etc/fdfs/tracker.conf restart
storage:fdfs_storaged /etc/fdfs/storage.conf restart
原文章地址:
https://blog.csdn.net/z13615480737/article/details/134134293
https://blog.csdn.net/packge/article/details/126451355