新增下载远程文件的接口、新增下载远程文件 url 白名单

This commit is contained in:
bwcx_jzy 2021-07-31 17:11:47 +08:00
parent 96520b6367
commit e6a55b1642
9 changed files with 236 additions and 167 deletions

View File

@ -35,7 +35,7 @@ public class IndexController extends BaseAgentController {
@RequestMapping(value = {"index", "", "index.html", "/"}, produces = MediaType.TEXT_PLAIN_VALUE)
@NotAuthorize
public String index() {
return "Jpom-Agent";
return "Jpom-Agent,Can't access directly,Please configure it to JPOM server";
}
@RequestMapping(value = "info", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

View File

@ -8,6 +8,7 @@ import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import cn.jiangzeyin.common.DefaultSystemLog;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.controller.multipart.MultipartFileBuilder;
@ -28,9 +29,7 @@ import io.jpom.util.FileUtils;
import io.jpom.util.StringUtil;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.File;
@ -39,6 +38,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 项目文件管理
@ -295,7 +295,7 @@ public class ProjectFileControl extends BaseAgentController {
* @param filename 读取的文件名
* @return json
*/
@RequestMapping(value = "read_file", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@GetMapping(value = "read_file", produces = MediaType.APPLICATION_JSON_VALUE)
public String readFile(String filePath, String filename) {
ProjectInfoModel pim = getProjectInfoModel();
filePath = StrUtil.emptyToDefault(filePath, File.separator);
@ -314,7 +314,7 @@ public class ProjectFileControl extends BaseAgentController {
* @param fileText 文件内容
* @return json
*/
@RequestMapping(value = "update_config_file", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@PostMapping(value = "update_config_file", produces = MediaType.APPLICATION_JSON_VALUE)
public String updateConfigFile(String filePath, String filename, String fileText) {
ProjectInfoModel pim = getProjectInfoModel();
filePath = StrUtil.emptyToDefault(filePath, File.separator);
@ -325,7 +325,15 @@ public class ProjectFileControl extends BaseAgentController {
}
@RequestMapping(value = "download", method = RequestMethod.GET)
/**
* 将执行文件下载到客户端 本地
*
* @param id 项目id
* @param filename 文件名
* @param levelName 文件夹名
* @return 正常情况返回文件流非正在返回 text plan
*/
@GetMapping(value = "download", produces = MediaType.APPLICATION_JSON_VALUE)
public String download(String id, String filename, String levelName) {
String safeFileName = pathSafe(filename);
if (StrUtil.isEmpty(safeFileName)) {
@ -333,12 +341,7 @@ public class ProjectFileControl extends BaseAgentController {
}
try {
ProjectInfoModel pim = projectInfoService.getItem(id);
File file;
if (StrUtil.isEmpty(levelName)) {
file = FileUtil.file(pim.allLib(), filename);
} else {
file = FileUtil.file(pim.allLib(), levelName, filename);
}
File file = FileUtil.file(pim.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
if (file.isDirectory()) {
return "暂不支持下载文件夹";
}
@ -349,4 +352,33 @@ public class ProjectFileControl extends BaseAgentController {
return "下载失败。请刷新页面后重试";
}
/**
* 下载远程文件
*
* @param id 项目id
* @param url 远程 url 地址
* @param levelName 保存的文件夹
* @return json
*/
@GetMapping(value = "remote_download", produces = MediaType.APPLICATION_JSON_VALUE)
public String remoteDownload(String id, String url, String levelName) {
if (StrUtil.isEmpty(url)) {
return JsonMessage.getString(405, "请输入正确的远程地址");
}
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
Set<String> allowRemoteDownloadHost = whitelist.getAllowRemoteDownloadHost();
Assert.state(CollUtil.isNotEmpty(allowRemoteDownloadHost), "还没有配置运行的远程地址");
List<String> collect = allowRemoteDownloadHost.stream().filter(s -> StrUtil.startWith(url, s)).collect(Collectors.toList());
Assert.state(CollUtil.isNotEmpty(collect), "不允许下载当前地址的文件");
try {
ProjectInfoModel pim = projectInfoService.getItem(id);
File file = FileUtil.file(pim.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR));
long downloadFile = HttpUtil.downloadFile(url, file);
return JsonMessage.getString(200, "下次成功文件大小:" + FileUtil.readableFileSize(downloadFile));
} catch (Exception e) {
DefaultSystemLog.getLog().error("下载远程文件异常", e);
return JsonMessage.getString(500, "下载远程文件失败:" + e.getMessage());
}
}
}

View File

@ -1,8 +1,10 @@
package io.jpom.controller.system;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.RegexPool;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.jiangzeyin.common.JsonMessage;
import io.jpom.common.BaseJpomController;
@ -46,7 +48,7 @@ public class WhitelistDirectoryController extends BaseJpomController {
@RequestMapping(value = "whitelistDirectory_submit", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String whitelistDirectorySubmit(String project, String certificate, String nginx, String allowEditSuffix) {
public String whitelistDirectorySubmit(String project, String certificate, String nginx, String allowEditSuffix, String allowRemoteDownloadHost) {
if (StrUtil.isEmpty(project)) {
return JsonMessage.getString(401, "项目路径白名单不能为空");
}
@ -55,7 +57,8 @@ public class WhitelistDirectoryController extends BaseJpomController {
List<String> certificateList = this.parseToList(certificate, "证书路径白名单不能为空");
List<String> nList = this.parseToList(nginx, "nginx路径白名单不能为空");
List<String> allowEditSuffixList = this.parseToList(allowEditSuffix, "运行编辑的文件后缀不能为空");
return save(list, certificateList, nList, allowEditSuffixList).toString();
List<String> allowRemoteDownloadHostList = this.parseToList(allowRemoteDownloadHost, "运行远程下载的 host 不能配置为空");
return save(list, certificateList, nList, allowEditSuffixList, allowRemoteDownloadHostList).toString();
}
//
// private JsonMessage<String> save(String project, List<String> certificate, List<String> nginx, List<String> allowEditSuffixList) {
@ -64,7 +67,11 @@ public class WhitelistDirectoryController extends BaseJpomController {
// }
private JsonMessage<String> save(List<String> projects, List<String> certificate, List<String> nginx, List<String> allowEditSuffixList) {
private JsonMessage<String> save(List<String> projects,
List<String> certificate,
List<String> nginx,
List<String> allowEditSuffixList,
List<String> allowRemoteDownloadHostList) {
List<String> projectArray;
{
projectArray = AgentWhitelist.covertToArray(projects);
@ -121,10 +128,14 @@ public class WhitelistDirectoryController extends BaseJpomController {
}
}
}
AgentWhitelist agentWhitelist = whitelistDirectoryService.getWhitelist();
if (agentWhitelist == null) {
agentWhitelist = new AgentWhitelist();
if (CollUtil.isNotEmpty(allowRemoteDownloadHostList)) {
for (String s : allowRemoteDownloadHostList) {
Assert.state(ReUtil.isMatch(RegexPool.URL_HTTP, s), "配置的远程地址不规范,请重新填写:" + s);
}
}
AgentWhitelist agentWhitelist = whitelistDirectoryService.getWhitelist();
agentWhitelist.setProject(projectArray);
agentWhitelist.setCertificate(certificateArray);
agentWhitelist.setNginx(nginxArray);

View File

@ -12,6 +12,7 @@ import io.jpom.system.ExtConfigBean;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 白名单
@ -38,6 +39,19 @@ public class AgentWhitelist extends BaseJsonModel {
*/
private List<String> allowEditSuffix;
/**
* 运行远程下载的 host
*/
private Set<String> allowRemoteDownloadHost;
public Set<String> getAllowRemoteDownloadHost() {
return allowRemoteDownloadHost;
}
public void setAllowRemoteDownloadHost(Set<String> allowRemoteDownloadHost) {
this.allowRemoteDownloadHost = allowRemoteDownloadHost;
}
public List<String> getAllowEditSuffix() {
return allowEditSuffix;
}

View File

@ -7,40 +7,41 @@ package io.jpom.plugin;
* @date 2019/8/13
*/
public enum MethodFeature {
/**
* 没有
*/
NULL(""),
/**
* 文件管理
*/
FILE("文件管理"),
EDIT("修改"),
DEL("删除"),
INSTALL("安装"),
LIST("列表"),
TERMINAL("终端"),
DOWNLOAD("下载"),
LOG("日志"),
UPLOAD("上传"),
// WHITELIST("白名单"),
EXECUTE("执行"),
DEL_FILE("删除文件"),
CACHE("缓存"),
DEL_LOG("删除日志"),
CONFIG("配置"),
READ_FILE("读取文件"),
GET_FILE_FOMAT("获取在线编辑文件格式"),
UPDATE_CONFIG_FILE("更新文件"),
;
/**
* 没有
*/
NULL(""),
/**
* 文件管理
*/
FILE("文件管理"),
EDIT("修改"),
DEL("删除"),
INSTALL("安装"),
LIST("列表"),
TERMINAL("终端"),
DOWNLOAD("下载"),
LOG("日志"),
UPLOAD("上传"),
// WHITELIST("白名单"),
EXECUTE("执行"),
DEL_FILE("删除文件"),
CACHE("缓存"),
DEL_LOG("删除日志"),
CONFIG("配置"),
READ_FILE("读取文件"),
// GET_FILE_FOMAT("获取在线编辑文件格式"),
UPDATE_CONFIG_FILE("更新文件"),
REMOTE_DOWNLOAD("下载远程文件"),
;
private String name;
private final String name;
public String getName() {
return name;
}
public String getName() {
return name;
}
MethodFeature(String name) {
this.name = name;
}
MethodFeature(String name) {
this.name = name;
}
}

View File

@ -20,113 +20,114 @@ import java.io.File;
*/
@Configuration
public class ConfigBean {
/**
* 用户名header
*/
public static final String JPOM_SERVER_USER_NAME = "Jpom-Server-UserName";
public static final String JPOM_AGENT_AUTHORIZE = "Jpom-Agent-Authorize";
/**
* 用户名header
*/
public static final String JPOM_SERVER_USER_NAME = "Jpom-Server-UserName";
public static final String DATA = "data";
public static final String JPOM_AGENT_AUTHORIZE = "Jpom-Agent-Authorize";
public static final int AUTHORIZE_ERROR = 900;
public static final String DATA = "data";
/**
* 授权信息
*/
public static final String AUTHORIZE = "agent_authorize.json";
/**
*
*/
public static final String AUTHORIZE_USER_KEY = "jpom.authorize.agentName";
/**
*
*/
public static final String AUTHORIZE_PWD_KEY = "jpom.authorize.agentPwd";
/**
* 程序升级信息文件
*/
public static final String UPGRADE = "upgrade.json";
/**
* Jpom 程序运行的 application 标识
*/
@Value("${jpom.applicationTag:}")
public String applicationTag;
/**
* 程序端口
*/
@Value("${server.port}")
private int port;
public static final int AUTHORIZE_ERROR = 900;
private static ConfigBean configBean;
/**
* 授权信息
*/
public static final String AUTHORIZE = "agent_authorize.json";
/**
*
*/
public static final String AUTHORIZE_USER_KEY = "jpom.authorize.agentName";
/**
*
*/
public static final String AUTHORIZE_PWD_KEY = "jpom.authorize.agentPwd";
/**
* 程序升级信息文件
*/
public static final String UPGRADE = "upgrade.json";
/**
* Jpom 程序运行的 application 标识
*/
@Value("${jpom.applicationTag:}")
public String applicationTag;
/**
* 程序端口
*/
@Value("${server.port}")
private int port;
/**
* 单利模式
*
* @return config
*/
public static ConfigBean getInstance() {
if (configBean == null) {
configBean = SpringUtil.getBean(ConfigBean.class);
}
return configBean;
}
private static ConfigBean configBean;
public int getPort() {
return port;
}
/**
* 单利模式
*
* @return config
*/
public static ConfigBean getInstance() {
if (configBean == null) {
configBean = SpringUtil.getBean(ConfigBean.class);
}
return configBean;
}
/**
* 获取项目运行数据存储文件夹路径
*
* @return 文件夹路径
*/
public String getDataPath() {
String dataPath = FileUtil.normalize(ExtConfigBean.getInstance().getPath() + "/" + DATA);
FileUtil.mkdir(dataPath);
return dataPath;
}
public int getPort() {
return port;
}
/**
* 获取pid文件
*
* @return file
*/
public File getPidFile() {
return new File(getDataPath(), StrUtil.format("pid.{}.{}",
JpomApplication.getAppType().name(), JpomManifest.getInstance().getPid()));
}
/**
* 获取项目运行数据存储文件夹路径
*
* @return 文件夹路径
*/
public String getDataPath() {
String dataPath = FileUtil.normalize(ExtConfigBean.getInstance().getPath() + "/" + DATA);
FileUtil.mkdir(dataPath);
return dataPath;
}
/**
* 获取当前项目全局 运行信息文件路径
*
* @param type 程序类型
* @return file
*/
public File getApplicationJpomInfo(Type type) {
return FileUtil.file(SystemUtil.getUserInfo().getTempDir(), "jpom", type.name());
}
/**
* 获取pid文件
*
* @return file
*/
public File getPidFile() {
return new File(getDataPath(), StrUtil.format("pid.{}.{}",
JpomApplication.getAppType().name(), JpomManifest.getInstance().getPid()));
}
/**
* 获取 agent 端自动生成的授权文件路径
*
* @param dataPath 指定数据路径
* @return file
*/
public String getAgentAutoAuthorizeFile(String dataPath) {
return FileUtil.normalize(dataPath + "/" + ConfigBean.AUTHORIZE);
}
/**
* 获取当前项目全局 运行信息文件路径
*
* @param type 程序类型
* @return file
*/
public File getApplicationJpomInfo(Type type) {
return FileUtil.file(SystemUtil.getUserInfo().getTempDir(), "jpom", type.name());
}
/**
* 获取 agent 端自动生成的授权文件路径
*
* @param dataPath 指定数据路径
* @return file
*/
public String getAgentAutoAuthorizeFile(String dataPath) {
return FileUtil.normalize(dataPath + "/" + ConfigBean.AUTHORIZE);
}
/**
* 获取临时文件存储路径
*
* @return file
*/
public File getTempPath() {
File file = new File(ConfigBean.getInstance().getDataPath());
file = new File(file.getPath() + "/temp/");
FileUtil.mkdir(file);
return file;
}
/**
* 获取临时文件存储路径
*
* @return file
*/
public File getTempPath() {
File file = new File(ConfigBean.getInstance().getDataPath());
file = new File(file.getPath() + "/temp/");
FileUtil.mkdir(file);
return file;
}
}

View File

@ -82,7 +82,7 @@ public enum NodeUrl {
Manage_File_ReadFile("/manage/file/read_file"),
Get_File_Format("/manage/file/getFileFormat"),
Manage_File_Remote_Download("/manage/file/remote_download"),
Manage_File_Download("/manage/file/download"),
@ -185,7 +185,7 @@ public enum NodeUrl {
/**
* 相对请求地址
*/
private String url;
private final String url;
private int timeOut;
public String getUrl() {

View File

@ -1,7 +1,5 @@
package io.jpom.controller.node.manage.file;
import cn.jiangzeyin.common.JsonMessage;
import com.alibaba.fastjson.JSONObject;
import io.jpom.common.BaseServerController;
import io.jpom.common.forward.NodeForward;
import io.jpom.common.forward.NodeUrl;
@ -11,12 +9,11 @@ import io.jpom.plugin.ClassFeature;
import io.jpom.plugin.Feature;
import io.jpom.plugin.MethodFeature;
import io.jpom.service.node.manage.ProjectInfoService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@ -25,15 +22,15 @@ import javax.annotation.Resource;
*
* @author Administrator
*/
@Controller
@RestController
@RequestMapping(value = "/node/manage/file/")
@Feature(cls = ClassFeature.PROJECT)
public class ProjectFileControl extends BaseServerController {
@Resource
private ProjectInfoService projectInfoService;
@Value("${fileFormat}")
private String fileFormat;
// @Value("${fileFormat}")
// private String fileFormat;
// /**
// * 文件管理页面
// *
@ -129,17 +126,30 @@ public class ProjectFileControl extends BaseServerController {
}
/**
* 获取可编辑文件格式
* 下载远程文件
*
* @return json
*/
@RequestMapping(value = "geFileFormat", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
@Feature(method = MethodFeature.GET_FILE_FOMAT)
public String geFileFormat() {
String[] file = fileFormat.split("\\|");
JSONObject jsonObject = new JSONObject();
jsonObject.put("fileFormat", file);
return JsonMessage.getString(200, "获取成功", jsonObject);
@RequestMapping(value = "remote_download", method = RequestMethod.GET)
@Feature(method = MethodFeature.REMOTE_DOWNLOAD)
public String remoteDownload() {
return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_File_Remote_Download).toString();
}
// /**
// * 获取可编辑文件格式
// *
// * @return json
// */
// @RequestMapping(value = "geFileFormat", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
// @ResponseBody
// @Feature(method = MethodFeature.GET_FILE_FOMAT)
// public String geFileFormat() {
// String[] file = fileFormat.split("\\|");
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("fileFormat", file);
// return JsonMessage.getString(200, "获取成功", jsonObject);
// }
}

View File

@ -32,4 +32,4 @@ request:
trimAll: true
parameterXss: false
#在线编辑格式
fileFormat: txt|yml|conf|properties|ini
#fileFormat: txt|yml|conf|properties|ini