更新 pom组件版本 新增安全秘钥接口 新增接口关闭 新增encryption接入方法 新增basic接入方法 新增User-Agent接入方法 支持ftp多用户 支持basic多用户 修复file接入协议错误 修复ssl伪证书错误 美化RUL报错提醒

This commit is contained in:
高雄
2025-12-25 17:04:18 +08:00
parent 92ca92bee6
commit 2dd008532a
14 changed files with 1774 additions and 769 deletions

View File

@@ -1,10 +1,14 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import io.mola.galimatias.GalimatiasParseException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.HtmlUtils;
@@ -17,8 +21,7 @@ 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.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -30,6 +33,18 @@ public class WebUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(WebUtils.class);
private static final String BASE64_MSG = "base64";
private static final String URL_PARAM_BASIC_NAME = "basic.name";
private static final String URL_PARAM_BASIC_PASS = "basic.pass";
private static final Map<String, String> ERROR_MESSAGES = Map.of(
"base64", "KK提醒您:接入方法错误未使用BASE64",
"base641", "KK提醒您:BASE64解码异常,确认是否正确使用BASE64编码",
"Keyerror", "KK提醒您:AES解码错误,请检测你的秘钥是否正确",
"base64error", "KK提醒您:你选用的是ASE加密,实际用了BASE64加密接入",
"byteerror", "KK提醒您:解码异常,检测你接入方法是否正确"
);
private static final String EMPTY_URL_MSG = "KK提醒您:地址不能为空";
private static final String INVALID_URL_MSG = "KK提醒您:请正确使用URL(必须包括https ftp file 协议)";
/**
* 获取标准的URL
*
@@ -234,17 +249,18 @@ public class WebUtils {
String urls = request.getParameter("urls");
String currentUrl = request.getParameter("currentUrl");
String urlPath = request.getParameter("urlPath");
String encryption = request.getParameter("encryption");
if (StringUtils.isNotBlank(url)) {
return decodeUrl(url);
return decodeUrl(url,encryption);
}
if (StringUtils.isNotBlank(currentUrl)) {
return decodeUrl(currentUrl);
return decodeUrl(currentUrl,encryption);
}
if (StringUtils.isNotBlank(urlPath)) {
return decodeUrl(urlPath);
return decodeUrl(urlPath,encryption);
}
if (StringUtils.isNotBlank(urls)) {
urls = decodeUrl(urls);
urls = decodeUrl(urls,encryption);
String[] images = urls.split("\\|");
return images[0];
}
@@ -268,13 +284,20 @@ public class WebUtils {
*
* 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;
public static String decodeUrl(String source,String encryption) {
String url;
if(ObjectUtils.isEmpty(encryption) || Objects.equals(ConfigConstants.getaesKey(), "false")){
encryption = "base64";
}
if(Objects.equals(encryption.toLowerCase(), "aes")){
return AESUtil.AesDecrypt(source);
}else {
url = decodeBase64String(source, StandardCharsets.UTF_8);
if(!isValidUrl(url)){
url="base641";
}
return url;
}
return url;
}
/**
@@ -301,6 +324,30 @@ public class WebUtils {
}
}
public static String urlSecurity(String url) {
if (ObjectUtils.isEmpty(url)) {
return EMPTY_URL_MSG;
}
// 检查已知的错误类型
String errorMsg = ERROR_MESSAGES.get(url);
if (errorMsg != null) {
return errorMsg;
}
// 验证URL格式
if (!isValidUrl(url)) {
return INVALID_URL_MSG;
}
// file协议特殊处理
if (url.toLowerCase().startsWith("file://")) {
// 对于本地文件,可以返回URL本身或进行特殊处理
// 根据业务需求决定:返回URL、返回特殊标识或进行本地文件安全检查
return url; // 或者返回特殊标识如 "file-protocol"
}
// 提取主机名
return getHost(url);
}
/**
* 获取 url 的 host
* @param urlStr url
@@ -371,4 +418,93 @@ public class WebUtils {
}
session.removeAttribute(key);
}
public static boolean validateKey(String key) {
String configKey = ConfigConstants.getKey();
return !"false".equals(configKey) && !configKey.equals(key);
}
public static String getContentTypeByFilename(String filename) {
String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
switch (extension) {
case "pdf": return "application/pdf";
case "jpg": case "jpeg": return "image/jpeg";
case "png": return "image/png";
case "gif": return "image/gif";
case "svg": return "image/svg+xml";
case "txt": return "text/plain";
case "html": case "htm": return "text/html";
case "xml": return "application/xml";
case "json": return "application/json";
default: return null;
}
}
/**
* name pass 获取用户名 和密码
*/
public static String[] namePass(String url,String name) {
url= getHost(url);
String[] items = name.split(",\\s*");
String toRemove = ":";
String names = null;
String[] parts = null;
try {
for (String item : items) {
int index = item.indexOf(toRemove);
if (index != -1) {
String result = item.substring(0, index);
if (Objects.equals(result, url)) {
names = item;
}
}
}
if (names !=null){
parts = names.split(toRemove);
}
} catch (Exception e) {
LOGGER.error("获取认证权限错误:",e);
}
return parts;
}
/**
* 支持basic 下载方法
*/
public static void applyBasicAuthHeaders(HttpHeaders headers, FileAttribute fileAttribute) {
String url = fileAttribute.getUrl();
// 从配置文件读取User-Agent,如果没有配置则使用默认值
String customUserAgent=ConfigConstants.getUserAgent();
String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
if (!StringUtils.isEmpty(customUserAgent) && !Objects.equals(customUserAgent, "false")) {
userAgent = customUserAgent;
}
headers.set("User-Agent", userAgent);
// 获取用户名和密码
String username = null;
String password = null;
// 从basic配置获取
String basic = ConfigConstants.getBasicName();
if (!StringUtils.isEmpty(basic) && !Objects.equals(basic, "false")) {
String[] urlUser = namePass(url, basic);
if (urlUser != null && urlUser.length >= 3) {
username = urlUser[1];
password = urlUser[2];
}
}
// URL参数优先
String basicUsername = getUrlParameterReg(url, URL_PARAM_BASIC_NAME);
String basicPassword = getUrlParameterReg(url, URL_PARAM_BASIC_PASS);
if (!StringUtils.isEmpty(basicUsername)) {
username = basicUsername;
password = basicPassword;
}
// 设置Basic Auth
if (!StringUtils.isEmpty(username)) {
String plainCredentials = username + ":" + (password != null ? password : "");
String base64Credentials = java.util.Base64.getEncoder().encodeToString(plainCredentials.getBytes());
headers.set("Authorization", "Basic " + base64Credentials);
}
}
}