Browse Source

补充上传文件类型拦截器

v4
chenrui 2 years ago
parent
commit
04acf38071
  1. 18
      lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/annotation/AdditionAllowUploadFileTypes.java
  2. 115
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FileTypeFilter.java
  3. 88
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FileTypeProperties.java
  4. 31
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FileUploadConfiguration.java
  5. 5
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FilterConfig.java
  6. 6
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ResourcesConfig.java

18
lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/annotation/AdditionAllowUploadFileTypes.java

@ -0,0 +1,18 @@
package com.zdxt.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AdditionAllowUploadFileTypes {
String[] value() default "";
}

115
lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FileTypeFilter.java

@ -0,0 +1,115 @@
package com.zdxt.auth.framework.config;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zdxt.common.ZDResponse;
import com.zdxt.common.annotation.AdditionAllowUploadFileTypes;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.lang.NonNull;
import org.springframework.messaging.handler.HandlerMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Component
public class FileTypeFilter implements HandlerInterceptor {
private final FileTypeProperties fileTypeProperties;
public FileTypeFilter(FileTypeProperties fileTypeProperties) {
this.fileTypeProperties = fileTypeProperties;
}
@Override
public boolean preHandle(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull Object handler) throws Exception {
if (!(request instanceof MultipartHttpServletRequest)) {
return true;
}
Map<String, MultipartFile> allFiles = ((MultipartHttpServletRequest) request).getFileMap();
List<String> notAllowedFiles = getNotAllowedFiles(handler, allFiles);
if (CollUtil.isNotEmpty(notAllowedFiles)) {
String message = "不被允许的文件类型!不被允许的文件列表如下:" + notAllowedFiles;
ServletUtil.write(response, JSONObject.toJSONString(ZDResponse.error(message)), MediaType.APPLICATION_JSON_UTF8_VALUE);
return false;
}
return true;
}
private List<String> getNotAllowedFiles(Object handler, Map<String, MultipartFile> allFiles) throws IOException {
List<String> notAllowedFilenames = null;
for (MultipartFile file : allFiles.values()) {
if (!isAllowedFile(file, handler)) {
if (notAllowedFilenames == null) {
notAllowedFilenames = new ArrayList<>();
}
notAllowedFilenames.add(file.getOriginalFilename());
}
}
return notAllowedFilenames;
}
boolean isAllowedFile(MultipartFile file, Object handler) throws IOException {
String fileName = file.getOriginalFilename();
try (InputStream in = file.getInputStream()) {
String type = FileTypeUtil.getType(in);
if (StringUtils.isBlank(type)) {
// 无法通过文件头或者扩展名识别文件类型。
return false;
}
String extType = FileUtil.extName(fileName);
if (StringUtils.isBlank(extType)) {
// 后缀读不到类型,直接拒绝
return false;
}
// 文件头类型和后缀类型都要满足白名单
if (CollectionUtils.containsAll(fileTypeProperties.getAllowedTypes(),
Lists.newArrayList(type.toLowerCase(Locale.ROOT), extType.toLowerCase(Locale.ROOT)))) {
return true;
}
String[] additionAllowUploadFileTypes = getAdditionAllowUploadFileTypes(handler);
return Arrays.stream(additionAllowUploadFileTypes)
.anyMatch(type::equalsIgnoreCase) &&
Arrays.stream(additionAllowUploadFileTypes)
.anyMatch(extType::equalsIgnoreCase);
}
}
private String[] getAdditionAllowUploadFileTypes(Object handle) {
String[] res = new String[0];
if (!(handle instanceof HandlerMethod)) {
return res;
}
HandlerMethod handlerMethod = (HandlerMethod) handle;
if (handlerMethod.hasMethodAnnotation(AdditionAllowUploadFileTypes.class)) {
AdditionAllowUploadFileTypes types = handlerMethod.getMethodAnnotation(AdditionAllowUploadFileTypes.class);
if (types != null) {
String[] allowedTypes = types.value();
if (allowedTypes != null) {
res = allowedTypes;
}
}
}
return res;
}
}

88
lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FileTypeProperties.java

@ -0,0 +1,88 @@
package com.zdxt.auth.framework.config;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* 默认支持上传:
* 1. 文档类 "xlsx", "xls", "docx", "doc", "pdf", "txt"
* 2. 图片/视频类: "jpg", "jpeg", "png", "bmp", "mp4"
* 3. 压缩包zip
*
* @author
*/
@Component
@ConfigurationProperties(value = "ruoyi.filetype")
public class FileTypeProperties {
private static final Logger LOGGER = LoggerFactory.getLogger(FileTypeProperties.class);
/**
* 默认允许的文件类型
*
* @see cn.hutool.core.io.FileTypeUtil
*/
private List<String> defaultAllowTypes = Lists.newArrayList(
"xlsx", "xls", "docx", "doc", "pdf", "txt",
"jpg", "jpeg", "bmp", "mp4",
"zip");
/**
* 自定义支持的扩展类型
*
* @see cn.hutool.core.io.FileTypeUtil
*/
private List<String> additionalAllowTypes;
private Set<String> allowedTypes;
public Set<String> getAllowedTypes() {
return allowedTypes;
}
public void setAllowedTypes(Set<String> allowedTypes) {
this.allowedTypes = allowedTypes;
}
public List<String> getAdditionalAllowTypes() {
return additionalAllowTypes;
}
public void setAdditionalAllowTypes(List<String> additionalAllowTypes) {
this.additionalAllowTypes = additionalAllowTypes;
}
@PostConstruct
public void preSetAllowedTypes() {
allowedTypes = new HashSet<>();
if (CollectionUtil.isNotEmpty(defaultAllowTypes)) {
for (String type : defaultAllowTypes) {
if (StrUtil.isNotBlank(type)) {
allowedTypes.add(type.toLowerCase(Locale.ROOT));
}
}
}
if (CollectionUtil.isNotEmpty(additionalAllowTypes)) {
for (String type : additionalAllowTypes) {
if (StrUtil.isNotBlank(type)) {
allowedTypes.add(type.toLowerCase(Locale.ROOT));
}
}
}
LOGGER.info("File Allowed Types 初始化完成!");
}
}

31
lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FileUploadConfiguration.java

@ -0,0 +1,31 @@
package com.zdxt.auth.framework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//@Configuration
public class FileUploadConfiguration implements WebMvcConfigurer {
@Bean
public WebMvcConfigurer multipartConfigurer() {
return new WebMvcConfigurer() {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
// 设置媒体类型
configurer.mediaType("json", MediaType.APPLICATION_JSON);
// 你可以继续添加更多的媒体类型
//图片
configurer.mediaType("png", MediaType.IMAGE_PNG);
configurer.mediaType("gif", MediaType.IMAGE_GIF);
configurer.mediaType("jpeg", MediaType.IMAGE_JPEG);
//TODO 视频
//文档类型 TODO doc
configurer.mediaType("pdf", MediaType.APPLICATION_PDF);
}
};
}
}

5
lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/FilterConfig.java

@ -36,6 +36,9 @@ public class FilterConfig
@Autowired
HostFilter hostFilter;
@Autowired
private FileTypeFilter fileTypeFilter;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean xssFilterRegistration()
@ -52,6 +55,7 @@ public class FilterConfig
registration.setInitParameters(initParameters);
return registration;
}
@Bean
public FilterRegistrationBean hostfilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
@ -61,6 +65,7 @@ public class FilterConfig
registration.setOrder(1); // 值越小,Filter越靠前。
return registration;
}
// @Bean
// public FilterRegistrationBean corsNewFilter() {
// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

6
lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ResourcesConfig.java

@ -23,6 +23,9 @@ public class ResourcesConfig implements WebMvcConfigurer
@Value("${shiro.user.indexUrl}")
private String indexUrl;
@Autowired
private FileTypeProperties fileTypeProperties;
@Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor;
@ -71,5 +74,8 @@ public class ResourcesConfig implements WebMvcConfigurer
"/app/thirdLogin/testLogin"
);
// 除了登录放行,其他接口都token验证
//文件类型拦截
registry.addInterceptor(new FileTypeFilter(fileTypeProperties));
}
}
Loading…
Cancel
Save