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

相关文章

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修

python写个唤醒睡眠电脑的脚本

《python写个唤醒睡眠电脑的脚本》这篇文章主要为大家详细介绍了如何使用python写个唤醒睡眠电脑的脚本,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 环境:win10python3.12问题描述:怎么用python写个唤醒睡眠电脑的脚本?解决方案:1.唤醒处于睡眠状

Java文件上传的多种实现方式

《Java文件上传的多种实现方式》文章主要介绍了文件上传接收接口的使用方法,包括获取文件信息、创建文件夹、保存文件到本地的两种方法,以及如何使用Postman进行接口调用... 目录Java文件上传的多方式1.文件上传接收文件接口2.接口主要内容部分3.postman接口调用总结Java文件上传的多方式1

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

bat脚本启动git bash窗口,并执行命令方式

《bat脚本启动gitbash窗口,并执行命令方式》本文介绍了如何在Windows服务器上使用cmd启动jar包时出现乱码的问题,并提供了解决方法——使用GitBash窗口启动并设置编码,通过编写s... 目录一、简介二、使用说明2.1 start.BAT脚本2.2 参数说明2.3 效果总结一、简介某些情