XSS 跨站脚本攻击预防(文件上传)

2024-06-03 19:12

本文主要是介绍XSS 跨站脚本攻击预防(文件上传),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

XSS 跨站脚本攻击预防(文件上传)

注意:可以根据需求自定义,改造为拦截器、或者 AOP 等方式实现

import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;/*** 文件上传-文件信息校验工具类* 作用:防止 xss 跨站脚本攻击*/
@Slf4j
public class FileUploadCheckUtils {/*** spring.servlet.multipart的bean对象*/private static final MultipartProperties multipartProperties = SpringUtil.getBean(MultipartProperties.class);/*** 以下变量参数可以自行补充*/// 文件类型常量public static final String JPEG = "jpeg";public static final String JPG = "jpg";public static final String PNG = "png";public static final String GIF = "gif";public static final String PDF = "pdf";public static final String ZIP = "zip";public static final String RAR = "rar";public static final String DOC = "doc";public static final String DOCX = "docx";public static final String XLS = "xls";public static final String XLSX = "xlsx";public static final String PPT = "ppt";public static final String PPTX = "pptx";// 魔数常量public static final String JPEG_MAGIC = "FFD8FF";public static final String JPG_MAGIC = "FFD8FF";public static final String PNG_MAGIC = "89504E47";public static final String GIF_MAGIC = "47494638";public static final String PDF_MAGIC = "25504446";public static final String ZIP_MAGIC = "504B0304";public static final String RAR_MAGIC = "52617221";public static final String DOC_MAGIC = "D0CF11E0";public static final String DOCX_MAGIC = "504B0304";public static final String XLS_MAGIC = "D0CF11E0";public static final String XLSX_MAGIC = "504B0304";public static final String PPT_MAGIC = "D0CF11E0";public static final String PPTX_MAGIC = "504B0304";// 允许的文件类型// key-value : 文件类型-文件魔数private static final Map<String, String> FILE_TYPE_MAGIC_NUMBERS = new HashMap<>();static {FILE_TYPE_MAGIC_NUMBERS.put(JPEG, JPEG_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(JPG, JPG_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(PNG, PNG_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(GIF, GIF_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(PDF, PDF_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(ZIP, ZIP_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(RAR, RAR_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(DOC, DOC_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(DOCX, DOCX_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(XLS, XLS_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(XLSX, XLSX_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(PPT, PPT_MAGIC);FILE_TYPE_MAGIC_NUMBERS.put(PPTX, PPTX_MAGIC);}/*** @param file             被校验文件* @param allowFileMaxSize 允许的文件大小,单位为字节* @return bool*/public static void isValidFile(MultipartFile file, Long allowFileMaxSize, String... fileTypes) {// 检查文件大小if (!isValidFileSize(file, allowFileMaxSize)) {throw new RuntimeException("上传文件大小超过限制: " + allowFileMaxSize);}// 检查文件类型String fileExt = getFileExtension(file);if (!isValidFileType(fileExt, fileTypes)) {log.error("暂不支持文件类型: {}", fileExt);throw new RuntimeException("暂不支持文件类型: " + fileExt);}// 额外的魔数校验if (!isValidFileMagic(file, fileTypes)) {throw new RuntimeException("文件内容和文件类型不匹配");}}/*** @param fileSuffix 文件后缀* @param fileTypes  支持的文件类型* @return*/private static boolean isValidFileType(String fileSuffix, String[] fileTypes) {boolean flag = false;if (fileTypes == null || fileTypes.length == 0) {flag = FILE_TYPE_MAGIC_NUMBERS.containsKey(fileSuffix.toLowerCase());} else {for (String fileType : fileTypes) {if (fileSuffix.equals(fileType)) {flag = true;}}}return flag;}/*** 校验文件大小** @param file             文件* @param allowFileMaxSize 允许的文件大小* @return*/private static boolean isValidFileSize(MultipartFile file, Long allowFileMaxSize) {if (allowFileMaxSize == null) {allowFileMaxSize = multipartProperties.getMaxFileSize().toBytes();}log.info("上传文件大小为: {}", file.getSize());return file.getSize() <= allowFileMaxSize;}/*** 文件魔数校验** @param file      文件* @param fileTypes 文件类型* @return*/private static boolean isValidFileMagic(MultipartFile file, String[] fileTypes) {byte[] bytes = new byte[4];try (InputStream fis = file.getInputStream()) {fis.read(bytes, 0, bytes.length);StringBuilder sb = new StringBuilder();for (byte b : bytes) {sb.append(String.format("%02X", b));}String magicNumber = sb.toString();log.info("上传文件的魔数为: {}", magicNumber);if (fileTypes == null || fileTypes.length == 0) {for (String magic : FILE_TYPE_MAGIC_NUMBERS.values()) {if (magicNumber.startsWith(magic)) {return true;}}} else {for (String fileType : fileTypes) {String magic = FILE_TYPE_MAGIC_NUMBERS.get(fileType);if (magicNumber.startsWith(magic)) {return true;}}}} catch (Exception e) {log.error("上传文件-流读取操作异常: {}", e.getMessage());return false;}return false;}/*** 返回文件后缀** @param file 文件* @return string*/private static String getFileExtension(MultipartFile file) {String suffix = "";String originalFilename = file.getOriginalFilename();if (originalFilename != null) {int lastIndex = originalFilename.lastIndexOf('.');if (lastIndex > 0) {suffix = originalFilename.substring(lastIndex + 1);}}log.info("上传的文件后缀为: {}", suffix);return suffix;}
}

这篇关于XSS 跨站脚本攻击预防(文件上传)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027868

相关文章

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

GitLab文件的上传与下载方式

《GitLab文件的上传与下载方式》:本文主要介绍GitLab文件的上传与下载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录GitLab 项目拉取到本地GitLab 项目上传方法方法 1:本地项目未初始化Git方法 2:本地项目已初始化GitGitLab 上

Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)

《Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)》本文主要介绍了Golang分布式锁实现,采用Redis+Lua脚本确保原子性,持可重入和自动续期,用于防止超卖及重复下单,具有一定... 目录1 概念应用场景分布式锁必备特性2 思路分析宕机与过期防止误删keyLua保证原子性可重入锁自动

Nginx 413修改上传文件大小限制的方法详解

《Nginx413修改上传文件大小限制的方法详解》在使用Nginx作为Web服务器时,有时会遇到客户端尝试上传大文件时返回​​413RequestEntityTooLarge​​... 目录1. 理解 ​​413 Request Entity Too Large​​ 错误2. 修改 Nginx 配置2.1

Java应用如何防止恶意文件上传

《Java应用如何防止恶意文件上传》恶意文件上传可能导致服务器被入侵,数据泄露甚至服务瘫痪,因此我们必须采取全面且有效的防范措施来保护Java应用的安全,下面我们就来看看具体的实现方法吧... 目录恶意文件上传的潜在风险常见的恶意文件上传手段防范恶意文件上传的关键策略严格验证文件类型检查文件内容控制文件存储

Java实现MinIO文件上传的加解密操作

《Java实现MinIO文件上传的加解密操作》在云存储场景中,数据安全是核心需求之一,MinIO作为高性能对象存储服务,支持通过客户端加密(CSE)在数据上传前完成加密,下面我们来看看如何通过Java... 目录一、背景与需求二、技术选型与原理1. 加密方案对比2. 核心算法选择三、完整代码实现1. 加密上

在React聊天应用中实现图片上传功能

《在React聊天应用中实现图片上传功能》在现代聊天应用中,除了文字和表情,图片分享也是一个重要的功能,本文将详细介绍如何在基于React的聊天应用中实现图片上传和预览功能,感兴趣的小伙伴跟着小编一起... 目录技术栈实现步骤1. 消息组件改造2. 图片预览组件3. 聊天输入组件改造功能特点使用说明注意事项

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

springboot上传zip包并解压至服务器nginx目录方式

《springboot上传zip包并解压至服务器nginx目录方式》:本文主要介绍springboot上传zip包并解压至服务器nginx目录方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录springboot上传zip包并解压至服务器nginx目录1.首先需要引入zip相关jar包2.然