系列文章
FastDFS系列(二):SpringBoot集成FastDFS
目录
前言
防盗链主要是为了防止自己的图片、音乐、视频、软件等资源被其他网站或者非白名单之内的网站引用。
大量的盗链很有可能造成自己的图片等设计得不到保障,其他盗链网站的请求疯狂涌向自己的文件服务器,在不知道的情况下,你的文件服务器成了别人的“后花园”。
FastDFS通过token验证方式的防止盗链,其主要是通过验证密钥的准确性和密钥的有效时间来判断,这里,密钥一定要是私有的,非公开的。
fastdfs-client-java jar包的构建方式请参照FastDFS系列(二):SpringBoot集成FastDFS,防盗链只是在基本的集成上添加了token的生成过程和路径的再构建过程。
防盗链访问地址类似:域名( ip:port ) / 组名 ( group ) / 磁盘 ( M00 ) / 目录( 00/00 )/ xxxxxxxxxxxxxx.jpg
配置
-
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.fdfs</groupId>
<artifactId>study</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>study</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.29-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-
fastdfs-client.properties
#fastDFS连接超时时间,针对socket套接字函数connect
connect_timeout_in_seconds = 5
#fastDFS网络超时时间
network_timeout_in_seconds = 30
#编码格式
charset = UTF-8
#是否启用token验证(针对fdfs配置文件http.conf,防盗链)
http_anti_steal_token = true
#连接密钥(http.conf要配置一样的密钥)
http_secret_key = FastDFS1234567890
#tracker服务器访问端口
http_tracker_http_port = 80
#tracker服务器地址,多个以逗号隔开
tracker_server = 192.168.1.106:22122
#是否启用连接池
connection_pool.enabled = true
#每一个IP:Port的最大连接数,0为没有限制
connection_pool.max_count_per_entry = 500
#每一个连接的最大空闲时间
connection_pool.max_idle_time = 3600
#达到最大连接数时候的最大等待时间
connection_pool.max_wait_time_in_ms = 1000
防盗链一定要设置 http_anti_steal_token = true ,这里的 http_secret_key 一定要于服务器端 http.config 里面的 http_secret_key 一致(默认都是 FastDFS1234567890 )
-
application.yml
server:
port: 9001
spring:
application:
name: fdfsClient
#fastDFS地址
fdfs:
remote-url: 192.168.1.106
这里主要是配置 fastDFS地址 ,方便修改和配置,也方便直接获取
-
主要逻辑
@Service
@PropertySource("classpath:fastdfs-client.properties")
public class UploadService {
/**
* 密钥
*/
@Value("${http_secret_key}")
private String secretKey;
/**
* 服务器地址
*/
@Value("${fdfs.remote-url}")
private String remoteUrl;
/**
* 上传逻辑
* @param file
* @return
*/
public String upload(MultipartFile file) {
//获取文件名
String filename = file.getOriginalFilename();
//获取文件类型
//TODO 最好根据content-type来判断
String extName= "";
if(filename.contains("."))
{
extName = filename.substring(filename.lastIndexOf(".")+1);
}
try {
StorageClient storageClient = buildClient();
//返回结果,第一个为组名,第二个为fdfs磁盘地址
String[] result = storageClient.upload_file(file.getBytes(), extName, null);
// String srcUrl = new StringBuffer(result[0]).append("/").append(result[1]).toString();
return tokenUrl(result[0],result[1]);
} catch (IOException | MyException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "上传失败!";
}
/**
* 防盗链地址
* @param group
* @param remoteFile
* @return
*/
public String tokenUrl(String group,String remoteFile) throws UnsupportedEncodingException, NoSuchAlgorithmException, MyException {
int ts = (int) (System.currentTimeMillis()/1000);
String token = ProtoCommon.getToken(remoteFile, ts, secretKey);
StringBuffer url = new StringBuffer(remoteUrl);
url.append("/")
.append(group)
.append("/")
.append(remoteFile)
.append("?")
.append("token=")
.append(token)
.append("&ts=")
.append(ts);
return url.toString();
}
/**
* 构建上传对象
* @return
*/
public StorageClient buildClient() throws IOException, MyException {
ClientGlobal.init("fastdfs-client.properties");
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getTrackerServer();
StorageClient storageClient = new StorageClient(trackerServer);
return storageClient;
}
}
1)这里主要通过 @PropertySource 加载我们指定的 fastdfs-client.properties 文件,然后通过 @Value 取值
2)这里加密的主要是文件地址,不要带上组名 ( group ),这里上传返回的数组,第一个为组名,第二个为文件地址
3)虽然加密不用组名,但是访问的时候要加上组名
-
http.conf
# HTTP default content type
http.default_content_type = application/octet-stream# MIME types mapping filename
# MIME types file format: MIME_type extensions
# such as: image/jpeg jpeg jpg jpe
# you can use apache's MIME file: mime.types
http.mime_types_filename = mime.types# if use token to anti-steal
# default value is false (0)
http.anti_steal.check_token = true# token TTL (time to live), seconds
# default value is 600
http.anti_steal.token_ttl = 18000# 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
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/upload/404.jpg# if support multi regions for HTTP Range
# default value is true
http.multi_range.enabed = true
1)http.anti_steal.check_token 是否开启token验证,这个值一定要设置为 true
2)http.anti_steal.secret_key 密钥,要注意是否跟项目内配置的一致
3)http.anti_steal.token_check_fail 验证失败返回文件,这个坑我太多,我以为要找不到文件才会去找这个地址,没想到启动 nginx它就会去确认这地址,这个值一定要配置对,切记
4)配置完 http.config 后,记得重启 nginx
测试
启动项目并且配置好 http.config 后,这里开始测试
- 测试上传
- 测试访问
这里是加上 token 和 ts 生成时间访问的,访问成功!!!
总结
- 防盗链的配置要注意:项目中和 http.config 都开启了 token验证
- FastDFS服务器时间和项目服务器时间要对得上,差距有得话也不要太大
- 个人来说,最坑的配置 http.anti_steal.token_check_fail 这个参数
- token 得生成也要注意一下,不要带上组名——group