下面是 SpringBoot 集成 FastDFS+Nginx 整合基于 Token 的防盗链的方法的完整攻略:
简介
FastDFS 是一个开源的分布式文件系统,由阿里巴巴的余庆编写,目前由开源社区进行开发,FastDFS 是基于 Linux 的文件系统,实现了一个简单的文件系统,它是以 Tracker Server 和 Storage Server 为两个服务端来运行的。Nginx 是目前非常流行的 Web 服务器软件,在线服务商也广泛采用 Nginx 作为服务端的软件之一。在使用 FastDFS 存储文件的时候,我们通常需要使用 Nginx 对文件进行访问,而防盗链可以有效的保护用户文件的安全性,防止 URL 被泄露并在未授权的情况下访问。
整合过程
- 添加 FastDFS 依赖
在 pom.xml 中添加 FastDFS 的依赖,这里我们使用的版本为1.27。
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.27.2</version>
</dependency>
- 配置 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;
}
}
- 配置 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;
}
}
}
- 集成 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;
}
}
}
- 编写防盗链拦截器
创建文件防盗链拦截器 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;
}
}
- 使用 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:文件上传
- 前端页面示例:
<!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>
- 文件上传控制器示例:
@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:文件下载
- 前端页面示例:
<!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>
- 文件下载控制器示例:
@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技术站