file-online-preview/server/src/main/java/cn/keking/utils/WebUtils.java

375 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package cn.keking.utils;
import io.mola.galimatias.GalimatiasParseException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.HtmlUtils;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author : kl
* create : 2020-12-27 1:30 上午
**/
public class WebUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(WebUtils.class);
private static final String BASE64_MSG = "base64";
/**
* 获取标准的URL
*
* @param urlStr url
* @return 标准的URL
*/
public static URL normalizedURL(String urlStr) throws GalimatiasParseException, MalformedURLException {
return io.mola.galimatias.URL.parse(urlStr).toJavaURL();
}
/**
* 对文件名进行编码
*
*/
public static String encodeFileName(String name) {
try {
name = URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
return null;
}
return name;
}
/**
* 去除fullfilename参数
*
* @param urlStr
* @return
*/
public static String clearFullfilenameParam(String urlStr) {
// 去除特定参数字段
Pattern pattern = Pattern.compile("(&fullfilename=[^&]*)");
Matcher matcher = pattern.matcher(urlStr);
return matcher.replaceAll("");
}
/**
* 对URL进行编码
*/
public static String urlEncoderencode(String urlStr) {
String fullFileName = getUrlParameterReg(urlStr, "fullfilename"); //获取流文件名
if (org.springframework.util.StringUtils.hasText(fullFileName)) {
// 移除fullfilename参数
urlStr = clearFullfilenameParam(urlStr);
} else {
fullFileName = getFileNameFromURL(urlStr); //获取文件名
}
if (KkFileUtils.isIllegalFileName(fullFileName)) { //判断文件名是否带有穿越漏洞
return null;
}
if (!UrlEncoderUtils.hasUrlEncoded(fullFileName)) { //判断文件名是否转义
try {
urlStr = URLEncoder.encode(urlStr, "UTF-8").replaceAll("\\+", "%20").replaceAll("%3A", ":").replaceAll("%2F", "/").replaceAll("%3F", "?").replaceAll("%26", "&").replaceAll("%3D", "=");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return urlStr;
}
/**
* 获取url中的参数
*
* @param url url
* @param name 参数名
* @return 参数值
*/
public static String getUrlParameterReg(String url, String name) {
Map<String, String> mapRequest = new HashMap<>();
String strUrlParam = truncateUrlPage(url);
if (strUrlParam == null) {
return "";
}
//每个键值为一组
String[] arrSplit = strUrlParam.split("[&]");
for (String strSplit : arrSplit) {
String[] arrSplitEqual = strSplit.split("[=]");
//解析出键值
if (arrSplitEqual.length > 1) {
//正确解析
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
} else if (!arrSplitEqual[0].equals("")) {
//只有参数没有值,不加入
mapRequest.put(arrSplitEqual[0], "");
}
}
return mapRequest.get(name);
}
/**
* 去掉url中的路径留下请求参数部分
*
* @param strURL url地址
* @return url请求参数部分
*/
private static String truncateUrlPage(String strURL) {
String strAllParam = null;
strURL = strURL.trim();
String[] arrSplit = strURL.split("[?]");
if (strURL.length() > 1) {
if (arrSplit.length > 1) {
if (arrSplit[1] != null) {
strAllParam = arrSplit[1];
}
}
}
return strAllParam;
}
/**
* 从url中剥离出文件名
*
* @param url 格式如http://www.com.cn/20171113164107_月度绩效表模板(新).xls?UCloudPublicKey=ucloudtangshd@weifenf.com14355492830001993909323&Expires=&Signature=I D1NOFtAJSPT16E6imv6JWuq0k=
* @return 文件名
*/
public static String getFileNameFromURL(String url) {
if (url.toLowerCase().startsWith("file:")) {
try {
URL urlObj = new URL(url);
url = urlObj.getPath().substring(1);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
// 因为url的参数中可能会存在/的情况所以直接url.lastIndexOf("/")会有问题
// 所以先从处将url截断然后运用url.lastIndexOf("/")获取文件名
String noQueryUrl = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
return noQueryUrl.substring(noQueryUrl.lastIndexOf("/") + 1);
}
/**
* 从url中剥离出文件名
* @param file 文件
* @return 文件名
*/
public static String getFileNameFromMultipartFile(MultipartFile file) {
String fileName = file.getOriginalFilename();
//判断是否为IE浏览器的文件名IE浏览器下文件名会带有盘符信
// escaping dangerous characters to prevent XSS
assert fileName != null;
fileName = HtmlUtils.htmlEscape(fileName, KkFileUtils.DEFAULT_FILE_ENCODING);
// Check for Unix-style path
int unixSep = fileName.lastIndexOf('/');
// Check for Windows-style path
int winSep = fileName.lastIndexOf('\\');
// Cut off at latest possible point
int pos = (Math.max(winSep, unixSep));
if (pos != -1) {
fileName = fileName.substring(pos + 1);
}
return fileName;
}
/**
* 从url中获取文件后缀
*
* @param url url
* @return 文件后缀
*/
public static String suffixFromUrl(String url) {
String nonPramStr = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
return KkFileUtils.suffixFromFileName(fileName);
}
/**
* 对url中的文件名进行UTF-8编码
*
* @param url url
* @return 文件名编码后的url
*/
public static String encodeUrlFileName(String url) {
String encodedFileName;
String noQueryUrl = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
int fileNameStartIndex = noQueryUrl.lastIndexOf('/') + 1;
int fileNameEndIndex = noQueryUrl.lastIndexOf('.');
if (fileNameEndIndex < fileNameStartIndex) {
return url;
}
try {
encodedFileName = URLEncoder.encode(noQueryUrl.substring(fileNameStartIndex, fileNameEndIndex), "UTF-8");
} catch (UnsupportedEncodingException e) {
return null;
}
return url.substring(0, fileNameStartIndex) + encodedFileName + url.substring(fileNameEndIndex);
}
/**
* 从 ServletRequest 获取预览的源 url , 已 base64 解码
*
* @param request 请求 request
* @return url
*/
public static String getSourceUrl(ServletRequest request) {
String url = request.getParameter("url");
String urls = request.getParameter("urls");
String currentUrl = request.getParameter("currentUrl");
String urlPath = request.getParameter("urlPath");
if (StringUtils.isNotBlank(url)) {
return decodeUrl(url);
}
if (StringUtils.isNotBlank(currentUrl)) {
return decodeUrl(currentUrl);
}
if (StringUtils.isNotBlank(urlPath)) {
return decodeUrl(urlPath);
}
if (StringUtils.isNotBlank(urls)) {
urls = decodeUrl(urls);
String[] images = urls.split("\\|");
return images[0];
}
return null;
}
/**
* 判断地址是否正确
* 高 2022/12/17
*/
public static boolean isValidUrl(String url) {
String regStr = "^((https|http|ftp|rtsp|mms|file)://)";//[.?*]表示匹配的就是本身
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(url);
return matcher.find();
}
/**
* 将 Base64 字符串解码再解码URL参数, 默认使用 UTF-8
* @param source 原始 Base64 字符串
* @return decoded string
*
* aHR0cHM6Ly9maWxlLmtla2luZy5jbi9kZW1vL%2BS4reaWhy5wcHR4 -> https://file.keking.cn/demo/%E4%B8%AD%E6%96%87.pptx -> https://file.keking.cn/demo/中文.pptx
*/
public static String decodeUrl(String source) {
String url = decodeBase64String(source, StandardCharsets.UTF_8);
if (! StringUtils.isNotBlank(url)){
return null;
}
return url;
}
/**
* 将 Base64 字符串使用指定字符集解码
* @param source 原始 Base64 字符串
* @param charsets 字符集
* @return decoded string
*/
public static String decodeBase64String(String source, Charset charsets) {
/*
* url 传入的参数里加号会被替换成空格,导致解析出错,这里需要把空格替换回加号
* 有些 Base64 实现可能每 76 个字符插入换行符,也一并去掉
* https://github.com/kekingcn/kkFileView/pull/340
*/
try {
return new String(Base64Utils.decodeFromString(source.replaceAll(" ", "+").replaceAll("\n", "")), charsets);
} catch (Exception e) {
if (e.getMessage().toLowerCase().contains(BASE64_MSG)) {
LOGGER.error("url解码异常接入方法错误未使用BASE64");
}else {
LOGGER.error("url解码异常其他错误", e);
}
return null;
}
}
/**
* 获取 url 的 host
* @param urlStr url
* @return host
*/
public static String getHost(String urlStr) {
try {
URL url = new URL(urlStr);
return url.getHost().toLowerCase();
} catch (MalformedURLException ignored) {
}
return null;
}
/**
* 获取 session 中的 String 属性
* @param request 请求
* @return 属性值
*/
public static String getSessionAttr(HttpServletRequest request, String key) {
HttpSession session = request.getSession();
if (session == null) {
return null;
}
Object value = session.getAttribute(key);
if (value == null) {
return null;
}
return value.toString();
}
/**
* 获取 session 中的 long 属性
* @param request 请求
* @param key 属性名
* @return 属性值
*/
public static long getLongSessionAttr(HttpServletRequest request, String key) {
String value = getSessionAttr(request, key);
if (value == null) {
return 0;
}
return Long.parseLong(value);
}
/**
* session 中设置属性
* @param request 请求
* @param key 属性名
*/
public static void setSessionAttr(HttpServletRequest request, String key, Object value) {
HttpSession session = request.getSession();
if (session == null) {
return;
}
session.setAttribute(key, value);
}
/**
* 移除 session 中的属性
* @param request 请求
* @param key 属性名
*/
public static void removeSessionAttr(HttpServletRequest request, String key) {
HttpSession session = request.getSession();
if (session == null) {
return;
}
session.removeAttribute(key);
}
}